* Sync with Wine 1.5.26.
CORE-7049
svn path=/trunk/; revision=58663
activex.c
array.c
bool.c
+ compile.c
date.c
+ decode.c
dispex.c
engine.c
error.c
global.c
jscript.c
jscript_main.c
+ jsregexp.c
+ jsstr.c
jsutils.c
lex.c
math.c
parser.tab.c
regexp.c
string.c
+ vbarray.c
rsrc.rc
${CMAKE_CURRENT_BINARY_DIR}/jscript.def)
add_library(jscript SHARED ${SOURCE})
+add_idl_headers(jscript_idlheader jscript_classes.idl)
+allow_warnings(jscript)
set_module_type(jscript win32dll)
target_link_libraries(jscript wine)
add_importlibs(jscript user32 ole32 oleaut32 advapi32 msvcrt kernel32 ntdll)
add_pch(jscript jscript.h)
# jsglobal.tlb needs stdole2.tlb
-add_dependencies(jscript stdole2)
+add_dependencies(jscript jscript_idlheader stdole2)
add_cd_file(TARGET jscript DESTINATION reactos/system32 FOR all)
set_source_files_properties(rsrc.rc PROPERTIES OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/jsglobal.tlb)
static IUnknown *create_activex_object(script_ctx_t *ctx, const WCHAR *progid)
{
- IInternetHostSecurityManager *secmgr;
+ IInternetHostSecurityManager *secmgr = NULL;
IObjectWithSite *obj_site;
struct CONFIRMSAFETY cs;
IClassFactoryEx *cfex;
GUID guid;
HRESULT hres;
+ TRACE("%s\n", debugstr_w(progid));
+
hres = CLSIDFromProgID(progid, &guid);
if(FAILED(hres))
return NULL;
TRACE("GUID %s\n", debugstr_guid(&guid));
- secmgr = get_sec_mgr(ctx);
- if(!secmgr)
- return NULL;
+ if(ctx->safeopt & INTERFACE_USES_SECURITY_MANAGER) {
+ secmgr = get_sec_mgr(ctx);
+ if(!secmgr)
+ return NULL;
- policy = 0;
- hres = IInternetHostSecurityManager_ProcessUrlAction(secmgr, URLACTION_ACTIVEX_RUN, (BYTE*)&policy, sizeof(policy),
- (BYTE*)&guid, sizeof(GUID), 0, 0);
- if(FAILED(hres) || policy != URLPOLICY_ALLOW)
- return NULL;
+ policy = 0;
+ hres = IInternetHostSecurityManager_ProcessUrlAction(secmgr, URLACTION_ACTIVEX_RUN,
+ (BYTE*)&policy, sizeof(policy), (BYTE*)&guid, sizeof(GUID), 0, 0);
+ if(FAILED(hres) || policy != URLPOLICY_ALLOW)
+ return NULL;
+ }
hres = CoGetClassObject(&guid, CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER, NULL, &IID_IClassFactory, (void**)&cf);
if(FAILED(hres))
if(FAILED(hres))
return NULL;
- cs.clsid = guid;
- cs.pUnk = obj;
- cs.dwFlags = 0;
- hres = IInternetHostSecurityManager_QueryCustomPolicy(secmgr, &GUID_CUSTOM_CONFIRMOBJECTSAFETY, &bpolicy, &policy_size,
- (BYTE*)&cs, sizeof(cs), 0);
- if(SUCCEEDED(hres)) {
- policy = policy_size >= sizeof(DWORD) ? *(DWORD*)bpolicy : URLPOLICY_DISALLOW;
- CoTaskMemFree(bpolicy);
- }
+ if(secmgr) {
+ cs.clsid = guid;
+ cs.pUnk = obj;
+ cs.dwFlags = 0;
+ hres = IInternetHostSecurityManager_QueryCustomPolicy(secmgr, &GUID_CUSTOM_CONFIRMOBJECTSAFETY,
+ &bpolicy, &policy_size, (BYTE*)&cs, sizeof(cs), 0);
+ if(SUCCEEDED(hres)) {
+ policy = policy_size >= sizeof(DWORD) ? *(DWORD*)bpolicy : URLPOLICY_DISALLOW;
+ CoTaskMemFree(bpolicy);
+ }
- if(FAILED(hres) || policy != URLPOLICY_ALLOW) {
- IUnknown_Release(obj);
- return NULL;
+ if(FAILED(hres) || policy != URLPOLICY_ALLOW) {
+ IUnknown_Release(obj);
+ return NULL;
+ }
}
hres = IUnknown_QueryInterface(obj, &IID_IObjectWithSite, (void**)&obj_site);
}
IObjectWithSite_Release(obj_site);
if(!ax_site || FAILED(hres)) {
- IObjectWithSite_Release(obj_site);
IUnknown_Release(obj);
return NULL;
}
return obj;
}
-static HRESULT ActiveXObject_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT ActiveXObject_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
+ jsstr_t * progid;
IDispatch *disp;
IUnknown *obj;
- BSTR progid;
HRESULT hres;
TRACE("\n");
return E_NOTIMPL;
}
- if(ctx->safeopt != (INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_DISPEX|INTERFACE_USES_SECURITY_MANAGER)) {
+ if(ctx->safeopt != (INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_DISPEX|INTERFACE_USES_SECURITY_MANAGER)
+ && ctx->safeopt != INTERFACE_USES_DISPEX) {
FIXME("Unsupported safeopt %x\n", ctx->safeopt);
return E_NOTIMPL;
}
- if(arg_cnt(dp) != 1) {
- FIXME("unsupported arg_cnt %d\n", arg_cnt(dp));
+ if(argc != 1) {
+ FIXME("unsupported argc %d\n", argc);
return E_NOTIMPL;
}
- hres = to_string(ctx, get_arg(dp,0), ei, &progid);
+ hres = to_string(ctx, argv[0], &progid);
if(FAILED(hres))
return hres;
- obj = create_activex_object(ctx, progid);
- SysFreeString(progid);
+ obj = create_activex_object(ctx, progid->str);
+ jsstr_release(progid);
if(!obj)
- return throw_generic_error(ctx, ei, IDS_CREATE_OBJ_ERROR, NULL);
+ return throw_generic_error(ctx, JS_E_CANNOT_CREATE_OBJ, NULL);
hres = IUnknown_QueryInterface(obj, &IID_IDispatch, (void**)&disp);
IUnknown_Release(obj);
return E_NOTIMPL;
}
- V_VT(retv) = VT_DISPATCH;
- V_DISPATCH(retv) = disp;
+ *r = jsval_disp(disp);
return S_OK;
}
-HRESULT create_activex_constr(script_ctx_t *ctx, DispatchEx **ret)
+HRESULT create_activex_constr(script_ctx_t *ctx, jsdisp_t **ret)
{
- DispatchEx *prototype;
+ jsdisp_t *prototype;
HRESULT hres;
static const WCHAR ActiveXObjectW[] = {'A','c','t','i','v','e','X','O','b','j','e','c','t',0};
#include <wine/config.h>
#include <wine/port.h>
-//#include <math.h>
+#include <math.h>
#include "jscript.h"
WINE_DEFAULT_DEBUG_CHANNEL(jscript);
typedef struct {
- DispatchEx dispex;
+ jsdisp_t dispex;
DWORD length;
} ArrayInstance;
return is_vclass(jsthis, JSCLASS_ARRAY) ? array_from_vdisp(jsthis) : NULL;
}
-static HRESULT get_length(script_ctx_t *ctx, vdisp_t *vdisp, jsexcept_t *ei, DispatchEx **jsthis, DWORD *ret)
+static HRESULT get_length(script_ctx_t *ctx, vdisp_t *vdisp, jsdisp_t **jsthis, DWORD *ret)
{
ArrayInstance *array;
- VARIANT var;
+ jsval_t val;
HRESULT hres;
array = array_this(vdisp);
}
if(!is_jsdisp(vdisp))
- return throw_type_error(ctx, ei, IDS_JSCRIPT_EXPECTED, NULL);
+ return throw_type_error(ctx, JS_E_JSCRIPT_EXPECTED, NULL);
- hres = jsdisp_propget_name(vdisp->u.jsdisp, lengthW, &var, ei, NULL/*FIXME*/);
+ hres = jsdisp_propget_name(vdisp->u.jsdisp, lengthW, &val);
if(FAILED(hres))
return hres;
- hres = to_uint32(ctx, &var, ei, ret);
- VariantClear(&var);
+ hres = to_uint32(ctx, val, ret);
+ jsval_release(val);
if(FAILED(hres))
return hres;
return S_OK;
}
-static HRESULT set_length(DispatchEx *obj, jsexcept_t *ei, DWORD length)
+static HRESULT set_length(jsdisp_t *obj, DWORD length)
{
- VARIANT var;
-
if(is_class(obj, JSCLASS_ARRAY)) {
((ArrayInstance*)obj)->length = length;
return S_OK;
}
- V_VT(&var) = VT_I4;
- V_I4(&var) = length;
- return jsdisp_propput_name(obj, lengthW, &var, ei, NULL/*FIXME*/);
+ return jsdisp_propput_name(obj, lengthW, jsval_number(length));
}
static WCHAR *idx_to_str(DWORD idx, WCHAR *ptr)
return ptr+1;
}
-static HRESULT Array_length(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT Array_length(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
ArrayInstance *This = array_from_vdisp(jsthis);
switch(flags) {
case DISPATCH_PROPERTYGET:
- V_VT(retv) = VT_I4;
- V_I4(retv) = This->length;
+ *r = jsval_number(This->length);
break;
case DISPATCH_PROPERTYPUT: {
- VARIANT num;
DOUBLE len = -1;
DWORD i;
HRESULT hres;
- hres = to_number(ctx, get_arg(dp, 0), ei, &num);
- if(V_VT(&num) == VT_I4)
- len = V_I4(&num);
- else
- len = floor(V_R8(&num));
+ hres = to_number(ctx, argv[0], &len);
+ if(FAILED(hres))
+ return hres;
+ len = floor(len);
if(len!=(DWORD)len)
- return throw_range_error(ctx, ei, IDS_INVALID_LENGTH, NULL);
+ return throw_range_error(ctx, JS_E_INVALID_LENGTH, NULL);
for(i=len; i<This->length; i++) {
hres = jsdisp_delete_idx(&This->dispex, i);
return S_OK;
}
-static HRESULT concat_array(DispatchEx *array, ArrayInstance *obj, DWORD *len,
- jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT concat_array(jsdisp_t *array, ArrayInstance *obj, DWORD *len)
{
- VARIANT var;
+ jsval_t val;
DWORD i;
HRESULT hres;
for(i=0; i < obj->length; i++) {
- hres = jsdisp_get_idx(&obj->dispex, i, &var, ei, caller);
+ hres = jsdisp_get_idx(&obj->dispex, i, &val);
if(hres == DISP_E_UNKNOWNNAME)
continue;
if(FAILED(hres))
return hres;
- hres = jsdisp_propput_idx(array, *len+i, &var, ei, caller);
- VariantClear(&var);
+ hres = jsdisp_propput_idx(array, *len+i, val);
+ jsval_release(val);
if(FAILED(hres))
return hres;
}
return S_OK;
}
-static HRESULT concat_obj(DispatchEx *array, IDispatch *obj, DWORD *len, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT concat_obj(jsdisp_t *array, IDispatch *obj, DWORD *len)
{
- DispatchEx *jsobj;
- VARIANT var;
+ jsdisp_t *jsobj;
HRESULT hres;
jsobj = iface_to_jsdisp((IUnknown*)obj);
if(jsobj) {
if(is_class(jsobj, JSCLASS_ARRAY)) {
- hres = concat_array(array, (ArrayInstance*)jsobj, len, ei, caller);
+ hres = concat_array(array, (ArrayInstance*)jsobj, len);
jsdisp_release(jsobj);
return hres;
}
jsdisp_release(jsobj);
}
- V_VT(&var) = VT_DISPATCH;
- V_DISPATCH(&var) = obj;
- return jsdisp_propput_idx(array, (*len)++, &var, ei, caller);
+ return jsdisp_propput_idx(array, (*len)++, jsval_disp(obj));
}
-static HRESULT Array_concat(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT Array_concat(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- DispatchEx *ret;
+ jsdisp_t *ret;
DWORD len = 0;
HRESULT hres;
if(FAILED(hres))
return hres;
- hres = concat_obj(ret, jsthis->u.disp, &len, ei, caller);
+ hres = concat_obj(ret, jsthis->u.disp, &len);
if(SUCCEEDED(hres)) {
- VARIANT *arg;
DWORD i;
- for(i=0; i < arg_cnt(dp); i++) {
- arg = get_arg(dp, i);
- if(V_VT(arg) == VT_DISPATCH)
- hres = concat_obj(ret, V_DISPATCH(arg), &len, ei, caller);
+ for(i=0; i < argc; i++) {
+ if(is_object_instance(argv[i]))
+ hres = concat_obj(ret, get_object(argv[i]), &len);
else
- hres = jsdisp_propput_idx(ret, len++, arg, ei, caller);
+ hres = jsdisp_propput_idx(ret, len++, argv[i]);
if(FAILED(hres))
break;
}
if(FAILED(hres))
return hres;
- if(retv) {
- V_VT(retv) = VT_DISPATCH;
- V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(ret);
- }else {
+ if(r)
+ *r = jsval_obj(ret);
+ else
jsdisp_release(ret);
- }
return S_OK;
}
-static HRESULT array_join(script_ctx_t *ctx, DispatchEx *array, DWORD length, const WCHAR *sep, VARIANT *retv,
- jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT array_join(script_ctx_t *ctx, jsdisp_t *array, DWORD length, const WCHAR *sep, jsval_t *r)
{
- BSTR *str_tab, ret = NULL;
- VARIANT var;
+ jsstr_t **str_tab, *ret = NULL;
+ jsval_t val;
DWORD i;
HRESULT hres = E_FAIL;
if(!length) {
- if(retv) {
- V_VT(retv) = VT_BSTR;
- V_BSTR(retv) = SysAllocStringLen(NULL, 0);
- if(!V_BSTR(retv))
- return E_OUTOFMEMORY;
- }
+ if(r)
+ *r = jsval_string(jsstr_empty());
return S_OK;
}
- str_tab = heap_alloc_zero(length * sizeof(BSTR));
+ str_tab = heap_alloc_zero(length * sizeof(*str_tab));
if(!str_tab)
return E_OUTOFMEMORY;
for(i=0; i < length; i++) {
- hres = jsdisp_get_idx(array, i, &var, ei, caller);
+ hres = jsdisp_get_idx(array, i, &val);
if(hres == DISP_E_UNKNOWNNAME) {
hres = S_OK;
continue;
} else if(FAILED(hres))
break;
- if(V_VT(&var) != VT_EMPTY && V_VT(&var) != VT_NULL)
- hres = to_string(ctx, &var, ei, str_tab+i);
- VariantClear(&var);
- if(FAILED(hres))
- break;
+ if(!is_undefined(val) && !is_null(val)) {
+ hres = to_string(ctx, val, str_tab+i);
+ jsval_release(val);
+ if(FAILED(hres))
+ break;
+ }
}
if(SUCCEEDED(hres)) {
seplen = strlenW(sep);
if(str_tab[0])
- len = SysStringLen(str_tab[0]);
- for(i=1; i < length; i++)
- len += seplen + SysStringLen(str_tab[i]);
+ len = jsstr_length(str_tab[0]);
+ for(i=1; i < length; i++) {
+ len += seplen;
+ if(str_tab[i])
+ len += jsstr_length(str_tab[i]);
+ if(len > JSSTR_MAX_LENGTH) {
+ hres = E_OUTOFMEMORY;
+ break;
+ }
+ }
- ret = SysAllocStringLen(NULL, len);
+ if(SUCCEEDED(hres))
+ ret = jsstr_alloc_buf(len);
if(ret) {
- DWORD tmplen = 0;
+ ptr = ret->str;
- if(str_tab[0]) {
- tmplen = SysStringLen(str_tab[0]);
- memcpy(ret, str_tab[0], tmplen*sizeof(WCHAR));
- }
+ if(str_tab[0])
+ ptr += jsstr_flush(str_tab[0], ptr);
- ptr = ret + tmplen;
for(i=1; i < length; i++) {
if(seplen) {
memcpy(ptr, sep, seplen*sizeof(WCHAR));
ptr += seplen;
}
- if(str_tab[i]) {
- tmplen = SysStringLen(str_tab[i]);
- memcpy(ptr, str_tab[i], tmplen*sizeof(WCHAR));
- ptr += tmplen;
- }
+ if(str_tab[i])
+ ptr += jsstr_flush(str_tab[i], ptr);
}
- *ptr=0;
}else {
hres = E_OUTOFMEMORY;
}
}
- for(i=0; i < length; i++)
- SysFreeString(str_tab[i]);
+ for(i=0; i < length; i++) {
+ if(str_tab[i])
+ jsstr_release(str_tab[i]);
+ }
heap_free(str_tab);
if(FAILED(hres))
return hres;
- TRACE("= %s\n", debugstr_w(ret));
-
- if(retv) {
- if(!ret) {
- ret = SysAllocStringLen(NULL, 0);
- if(!ret)
- return E_OUTOFMEMORY;
- }
-
- V_VT(retv) = VT_BSTR;
- V_BSTR(retv) = ret;
- }else {
- SysFreeString(ret);
- }
+ TRACE("= %s\n", debugstr_jsstr(ret));
+ if(r)
+ *r = jsval_string(ret);
+ else
+ jsstr_release(ret);
return S_OK;
}
/* ECMA-262 3rd Edition 15.4.4.5 */
-static HRESULT Array_join(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT Array_join(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- DispatchEx *jsthis;
+ jsdisp_t *jsthis;
DWORD length;
HRESULT hres;
TRACE("\n");
- hres = get_length(ctx, vthis, ei, &jsthis, &length);
+ hres = get_length(ctx, vthis, &jsthis, &length);
if(FAILED(hres))
return hres;
- if(arg_cnt(dp)) {
- BSTR sep;
+ if(argc) {
+ jsstr_t *sep;
- hres = to_string(ctx, get_arg(dp,0), ei, &sep);
+ hres = to_string(ctx, argv[0], &sep);
if(FAILED(hres))
return hres;
- hres = array_join(ctx, jsthis, length, sep, retv, ei, caller);
+ hres = array_join(ctx, jsthis, length, sep->str, r);
- SysFreeString(sep);
+ jsstr_release(sep);
}else {
- hres = array_join(ctx, jsthis, length, default_separatorW, retv, ei, caller);
+ hres = array_join(ctx, jsthis, length, default_separatorW, r);
}
return hres;
}
-static HRESULT Array_pop(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT Array_pop(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- DispatchEx *jsthis;
- VARIANT val;
+ jsdisp_t *jsthis;
+ jsval_t val;
DWORD length;
HRESULT hres;
TRACE("\n");
- hres = get_length(ctx, vthis, ei, &jsthis, &length);
+ hres = get_length(ctx, vthis, &jsthis, &length);
if(FAILED(hres))
return hres;
if(!length) {
- hres = set_length(jsthis, ei, 0);
+ hres = set_length(jsthis, 0);
if(FAILED(hres))
return hres;
- if(retv)
- V_VT(retv) = VT_EMPTY;
+ if(r)
+ *r = jsval_undefined();
return S_OK;
}
length--;
- hres = jsdisp_get_idx(jsthis, length, &val, ei, caller);
- if(SUCCEEDED(hres)) {
+ hres = jsdisp_get_idx(jsthis, length, &val);
+ if(SUCCEEDED(hres))
hres = jsdisp_delete_idx(jsthis, length);
- } else if(hres == DISP_E_UNKNOWNNAME) {
- V_VT(&val) = VT_EMPTY;
- hres = S_OK;
- } else
+ else if(hres == DISP_E_UNKNOWNNAME)
+ val = jsval_undefined();
+ else
return hres;
if(SUCCEEDED(hres))
- hres = set_length(jsthis, ei, length);
+ hres = set_length(jsthis, length);
if(FAILED(hres)) {
- VariantClear(&val);
+ jsval_release(val);
return hres;
}
- if(retv)
- *retv = val;
+ if(r)
+ *r = val;
else
- VariantClear(&val);
-
- return S_OK;
+ jsval_release(val);
+ return hres;
}
/* ECMA-262 3rd Edition 15.4.4.7 */
-static HRESULT Array_push(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT Array_push(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- DispatchEx *jsthis;
+ jsdisp_t *jsthis;
DWORD length = 0;
- int i, n;
+ unsigned i;
HRESULT hres;
TRACE("\n");
- hres = get_length(ctx, vthis, ei, &jsthis, &length);
+ hres = get_length(ctx, vthis, &jsthis, &length);
if(FAILED(hres))
return hres;
- n = arg_cnt(dp);
- for(i=0; i < n; i++) {
- hres = jsdisp_propput_idx(jsthis, length+i, get_arg(dp, i), ei, sp);
+ for(i=0; i < argc; i++) {
+ hres = jsdisp_propput_idx(jsthis, length+i, argv[i]);
if(FAILED(hres))
return hres;
}
- hres = set_length(jsthis, ei, length+n);
+ hres = set_length(jsthis, length+argc);
if(FAILED(hres))
return hres;
- if(retv) {
- V_VT(retv) = VT_I4;
- V_I4(retv) = length+n;
- }
+ if(r)
+ *r = jsval_number(length+argc);
return S_OK;
}
-static HRESULT Array_reverse(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT Array_reverse(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- DispatchEx *jsthis;
+ jsdisp_t *jsthis;
DWORD length, k, l;
- VARIANT v1, v2;
+ jsval_t v1, v2;
HRESULT hres1, hres2;
TRACE("\n");
- hres1 = get_length(ctx, vthis, ei, &jsthis, &length);
+ hres1 = get_length(ctx, vthis, &jsthis, &length);
if(FAILED(hres1))
return hres1;
for(k=0; k<length/2; k++) {
l = length-k-1;
- hres1 = jsdisp_get_idx(jsthis, k, &v1, ei, sp);
+ hres1 = jsdisp_get_idx(jsthis, k, &v1);
if(FAILED(hres1) && hres1!=DISP_E_UNKNOWNNAME)
return hres1;
- hres2 = jsdisp_get_idx(jsthis, l, &v2, ei, sp);
+ hres2 = jsdisp_get_idx(jsthis, l, &v2);
if(FAILED(hres2) && hres2!=DISP_E_UNKNOWNNAME) {
- VariantClear(&v1);
+ jsval_release(v1);
return hres2;
}
if(hres1 == DISP_E_UNKNOWNNAME)
hres1 = jsdisp_delete_idx(jsthis, l);
else
- hres1 = jsdisp_propput_idx(jsthis, l, &v1, ei, sp);
+ hres1 = jsdisp_propput_idx(jsthis, l, v1);
if(FAILED(hres1)) {
- VariantClear(&v1);
- VariantClear(&v2);
+ jsval_release(v1);
+ jsval_release(v2);
return hres1;
}
if(hres2 == DISP_E_UNKNOWNNAME)
hres2 = jsdisp_delete_idx(jsthis, k);
else
- hres2 = jsdisp_propput_idx(jsthis, k, &v2, ei, sp);
+ hres2 = jsdisp_propput_idx(jsthis, k, v2);
if(FAILED(hres2)) {
- VariantClear(&v2);
+ jsval_release(v2);
return hres2;
}
}
- if(retv) {
- V_VT(retv) = VT_DISPATCH;
- V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(jsthis);
- IDispatch_AddRef(V_DISPATCH(retv));
- }
-
+ if(r)
+ *r = jsval_obj(jsdisp_addref(jsthis));
return S_OK;
}
/* ECMA-262 3rd Edition 15.4.4.9 */
-static HRESULT Array_shift(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT Array_shift(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- DispatchEx *jsthis;
+ jsdisp_t *jsthis;
DWORD length = 0, i;
- VARIANT v, ret;
+ jsval_t v, ret;
HRESULT hres;
TRACE("\n");
- hres = get_length(ctx, vthis, ei, &jsthis, &length);
+ hres = get_length(ctx, vthis, &jsthis, &length);
if(FAILED(hres))
return hres;
if(!length) {
- hres = set_length(jsthis, ei, 0);
+ hres = set_length(jsthis, 0);
if(FAILED(hres))
return hres;
}
if(!length) {
- if(retv)
- V_VT(retv) = VT_EMPTY;
+ if(r)
+ *r = jsval_undefined();
return S_OK;
}
- hres = jsdisp_get_idx(jsthis, 0, &ret, ei, caller);
+ hres = jsdisp_get_idx(jsthis, 0, &ret);
if(hres == DISP_E_UNKNOWNNAME) {
- V_VT(&ret) = VT_EMPTY;
+ ret = jsval_undefined();
hres = S_OK;
}
for(i=1; SUCCEEDED(hres) && i<length; i++) {
- hres = jsdisp_get_idx(jsthis, i, &v, ei, caller);
+ hres = jsdisp_get_idx(jsthis, i, &v);
if(hres == DISP_E_UNKNOWNNAME)
hres = jsdisp_delete_idx(jsthis, i-1);
else if(SUCCEEDED(hres))
- hres = jsdisp_propput_idx(jsthis, i-1, &v, ei, caller);
+ hres = jsdisp_propput_idx(jsthis, i-1, v);
}
if(SUCCEEDED(hres)) {
hres = jsdisp_delete_idx(jsthis, length-1);
if(SUCCEEDED(hres))
- hres = set_length(jsthis, ei, length-1);
+ hres = set_length(jsthis, length-1);
}
- if(SUCCEEDED(hres) && retv)
- *retv = ret;
+ if(FAILED(hres))
+ return hres;
+
+ if(r)
+ *r = ret;
else
- VariantClear(&ret);
+ jsval_release(ret);
return hres;
}
/* ECMA-262 3rd Edition 15.4.4.10 */
-static HRESULT Array_slice(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT Array_slice(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r)
{
- DispatchEx *arr, *jsthis;
- VARIANT v;
+ jsdisp_t *arr, *jsthis;
DOUBLE range;
DWORD length, start, end, idx;
HRESULT hres;
TRACE("\n");
- hres = get_length(ctx, vthis, ei, &jsthis, &length);
+ hres = get_length(ctx, vthis, &jsthis, &length);
if(FAILED(hres))
return hres;
- if(arg_cnt(dp)) {
- hres = to_number(ctx, get_arg(dp, 0), ei, &v);
+ if(argc) {
+ hres = to_number(ctx, argv[0], &range);
if(FAILED(hres))
return hres;
- if(V_VT(&v) == VT_I4)
- range = V_I4(&v);
- else
- range = floor(V_R8(&v));
-
+ range = floor(range);
if(-range>length || isnan(range)) start = 0;
else if(range < 0) start = range+length;
else if(range <= length) start = range;
}
else start = 0;
- if(arg_cnt(dp)>1) {
- hres = to_number(ctx, get_arg(dp, 1), ei, &v);
+ if(argc > 1) {
+ hres = to_number(ctx, argv[1], &range);
if(FAILED(hres))
return hres;
- if(V_VT(&v) == VT_I4)
- range = V_I4(&v);
- else
- range = floor(V_R8(&v));
-
+ range = floor(range);
if(-range>length) end = 0;
else if(range < 0) end = range+length;
else if(range <= length) end = range;
return hres;
for(idx=start; idx<end; idx++) {
- hres = jsdisp_get_idx(jsthis, idx, &v, ei, sp);
+ jsval_t v;
+
+ hres = jsdisp_get_idx(jsthis, idx, &v);
if(hres == DISP_E_UNKNOWNNAME)
continue;
if(SUCCEEDED(hres)) {
- hres = jsdisp_propput_idx(arr, idx-start, &v, ei, sp);
- VariantClear(&v);
+ hres = jsdisp_propput_idx(arr, idx-start, v);
+ jsval_release(v);
}
if(FAILED(hres)) {
}
}
- if(retv) {
- V_VT(retv) = VT_DISPATCH;
- V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(arr);
- }
+ if(r)
+ *r = jsval_obj(arr);
else
jsdisp_release(arr);
return S_OK;
}
-static HRESULT sort_cmp(script_ctx_t *ctx, DispatchEx *cmp_func, VARIANT *v1, VARIANT *v2, jsexcept_t *ei,
- IServiceProvider *caller, INT *cmp)
+static HRESULT sort_cmp(script_ctx_t *ctx, jsdisp_t *cmp_func, jsval_t v1, jsval_t v2, INT *cmp)
{
HRESULT hres;
if(cmp_func) {
- VARIANTARG args[2];
- DISPPARAMS dp = {args, NULL, 2, 0};
- VARIANT tmp;
- VARIANT res;
+ jsval_t args[2];
+ jsval_t res;
+ double n;
- args[0] = *v2;
- args[1] = *v1;
+ args[0] = v1;
+ args[1] = v2;
- hres = jsdisp_call_value(cmp_func, DISPATCH_METHOD, &dp, &res, ei, caller);
+ hres = jsdisp_call_value(cmp_func, NULL, DISPATCH_METHOD, 2, args, &res);
if(FAILED(hres))
return hres;
- hres = to_number(ctx, &res, ei, &tmp);
- VariantClear(&res);
+ hres = to_number(ctx, res, &n);
+ jsval_release(res);
if(FAILED(hres))
return hres;
- if(V_VT(&tmp) == VT_I4)
- *cmp = V_I4(&tmp);
- else
- *cmp = V_R8(&tmp) > 0.0 ? 1 : -1;
- }else if(V_VT(v1) == VT_EMPTY) {
- *cmp = V_VT(v2) == VT_EMPTY ? 0 : 1;
- }else if(V_VT(v2) == VT_EMPTY) {
+ if(n == 0)
+ *cmp = 0;
+ *cmp = n > 0.0 ? 1 : -1;
+ }else if(is_undefined(v1)) {
+ *cmp = is_undefined(v2) ? 0 : 1;
+ }else if(is_undefined(v2)) {
*cmp = -1;
- }else if(is_num_vt(V_VT(v1)) && is_num_vt(V_VT(v2))) {
- DOUBLE d = num_val(v1)-num_val(v2);
+ }else if(is_number(v1) && is_number(v2)) {
+ double d = get_number(v1)-get_number(v2);
if(d > 0.0)
*cmp = 1;
else
*cmp = d < -0.0 ? -1 : 0;
}else {
- BSTR x, y;
+ jsstr_t *x, *y;
- hres = to_string(ctx, v1, ei, &x);
+ hres = to_string(ctx, v1, &x);
if(FAILED(hres))
return hres;
- hres = to_string(ctx, v2, ei, &y);
+ hres = to_string(ctx, v2, &y);
if(SUCCEEDED(hres)) {
- *cmp = strcmpW(x, y);
- SysFreeString(y);
+ *cmp = jsstr_cmp(x, y);
+ jsstr_release(y);
}
- SysFreeString(x);
+ jsstr_release(x);
if(FAILED(hres))
return hres;
}
}
/* ECMA-262 3rd Edition 15.4.4.11 */
-static HRESULT Array_sort(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT Array_sort(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- DispatchEx *jsthis, *cmp_func = NULL;
- VARIANT *vtab, **sorttab = NULL;
+ jsdisp_t *jsthis, *cmp_func = NULL;
+ jsval_t *vtab, **sorttab = NULL;
DWORD length;
DWORD i;
HRESULT hres = S_OK;
TRACE("\n");
- hres = get_length(ctx, vthis, ei, &jsthis, &length);
+ hres = get_length(ctx, vthis, &jsthis, &length);
if(FAILED(hres))
return hres;
- if(arg_cnt(dp) > 1) {
- WARN("invalid arg_cnt %d\n", arg_cnt(dp));
+ if(argc > 1) {
+ WARN("invalid arg_cnt %d\n", argc);
return E_FAIL;
}
- if(arg_cnt(dp) == 1) {
- VARIANT *arg = get_arg(dp, 0);
-
- if(V_VT(arg) != VT_DISPATCH) {
+ if(argc == 1) {
+ if(!is_object_instance(argv[0])) {
WARN("arg is not dispatch\n");
return E_FAIL;
}
-
- cmp_func = iface_to_jsdisp((IUnknown*)V_DISPATCH(arg));
+ cmp_func = iface_to_jsdisp((IUnknown*)get_object(argv[0]));
if(!cmp_func || !is_class(cmp_func, JSCLASS_FUNCTION)) {
WARN("cmp_func is not a function\n");
if(cmp_func)
if(!length) {
if(cmp_func)
jsdisp_release(cmp_func);
- if(retv) {
- V_VT(retv) = VT_DISPATCH;
- V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(jsthis);
- IDispatch_AddRef(V_DISPATCH(retv));
- }
+ if(r)
+ *r = jsval_obj(jsdisp_addref(jsthis));
return S_OK;
}
- vtab = heap_alloc_zero(length * sizeof(VARIANT));
+ vtab = heap_alloc_zero(length * sizeof(*vtab));
if(vtab) {
for(i=0; i<length; i++) {
- hres = jsdisp_get_idx(jsthis, i, vtab+i, ei, caller);
+ hres = jsdisp_get_idx(jsthis, i, vtab+i);
if(hres == DISP_E_UNKNOWNNAME) {
- V_VT(vtab+i) = VT_EMPTY;
+ vtab[i] = jsval_undefined();
hres = S_OK;
} else if(FAILED(hres)) {
WARN("Could not get elem %d: %08x\n", i, hres);
}
if(SUCCEEDED(hres)) {
- sorttab = heap_alloc(length*2*sizeof(VARIANT*));
+ sorttab = heap_alloc(length*2*sizeof(*sorttab));
if(!sorttab)
hres = E_OUTOFMEMORY;
}
/* merge-sort */
if(SUCCEEDED(hres)) {
- VARIANT *tmpv, **tmpbuf;
+ jsval_t *tmpv, **tmpbuf;
INT cmp;
tmpbuf = sorttab + length;
sorttab[i] = vtab+i;
for(i=0; i < length/2; i++) {
- hres = sort_cmp(ctx, cmp_func, sorttab[2*i+1], sorttab[2*i], ei, caller, &cmp);
+ hres = sort_cmp(ctx, cmp_func, *sorttab[2*i+1], *sorttab[2*i], &cmp);
if(FAILED(hres))
break;
else
bend = length - (i+k);
- memcpy(tmpbuf, sorttab+i, k*sizeof(VARIANT*));
+ memcpy(tmpbuf, sorttab+i, k*sizeof(jsval_t*));
while(a < k && b < bend) {
- hres = sort_cmp(ctx, cmp_func, tmpbuf[a], sorttab[i+k+b], ei, caller, &cmp);
+ hres = sort_cmp(ctx, cmp_func, *tmpbuf[a], *sorttab[i+k+b], &cmp);
if(FAILED(hres))
break;
break;
if(a < k)
- memcpy(sorttab+i+a+b, tmpbuf+a, (k-a)*sizeof(VARIANT*));
+ memcpy(sorttab+i+a+b, tmpbuf+a, (k-a)*sizeof(jsval_t*));
}
if(FAILED(hres))
}
for(i=0; SUCCEEDED(hres) && i < length; i++)
- hres = jsdisp_propput_idx(jsthis, i, sorttab[i], ei, caller);
+ hres = jsdisp_propput_idx(jsthis, i, *sorttab[i]);
}
if(vtab) {
for(i=0; i < length; i++)
- VariantClear(vtab+i);
+ jsval_release(vtab[i]);
heap_free(vtab);
}
heap_free(sorttab);
if(FAILED(hres))
return hres;
- if(retv) {
- V_VT(retv) = VT_DISPATCH;
- V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(jsthis);
- IDispatch_AddRef(V_DISPATCH(retv));
- }
-
+ if(r)
+ *r = jsval_obj(jsdisp_addref(jsthis));
return S_OK;
}
/* ECMA-262 3rd Edition 15.4.4.12 */
-static HRESULT Array_splice(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT Array_splice(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- DWORD length, start=0, delete_cnt=0, argc, i, add_args = 0;
- DispatchEx *ret_array = NULL, *jsthis;
- VARIANT v;
+ DWORD length, start=0, delete_cnt=0, i, add_args = 0;
+ jsdisp_t *ret_array = NULL, *jsthis;
+ jsval_t val;
+ double d;
+ int n;
HRESULT hres = S_OK;
TRACE("\n");
- hres = get_length(ctx, vthis, ei, &jsthis, &length);
+ hres = get_length(ctx, vthis, &jsthis, &length);
if(FAILED(hres))
return hres;
- argc = arg_cnt(dp);
- if(argc >= 1) {
- hres = to_integer(ctx, get_arg(dp,0), ei, &v);
+ if(argc) {
+ hres = to_integer(ctx, argv[0], &d);
if(FAILED(hres))
return hres;
- if(V_VT(&v) == VT_I4) {
- if(V_I4(&v) >= 0)
- start = min(V_I4(&v), length);
+ if(is_int32(d)) {
+ if((n = d) >= 0)
+ start = min(n, length);
else
- start = -V_I4(&v) > length ? 0 : length + V_I4(&v);
+ start = -n > length ? 0 : length + n;
}else {
- start = V_R8(&v) < 0.0 ? 0 : length;
+ start = d < 0.0 ? 0 : length;
}
}
if(argc >= 2) {
- hres = to_integer(ctx, get_arg(dp,1), ei, &v);
+ hres = to_integer(ctx, argv[1], &d);
if(FAILED(hres))
return hres;
- if(V_VT(&v) == VT_I4) {
- if(V_I4(&v) > 0)
- delete_cnt = min(V_I4(&v), length-start);
- }else if(V_R8(&v) > 0.0) {
+ if(is_int32(d)) {
+ if((n = d) > 0)
+ delete_cnt = min(n, length-start);
+ }else if(d > 0.0) {
delete_cnt = length-start;
}
add_args = argc-2;
}
- if(retv) {
+ if(r) {
hres = create_array(ctx, 0, &ret_array);
if(FAILED(hres))
return hres;
for(i=0; SUCCEEDED(hres) && i < delete_cnt; i++) {
- hres = jsdisp_get_idx(jsthis, start+i, &v, ei, caller);
- if(hres == DISP_E_UNKNOWNNAME)
+ hres = jsdisp_get_idx(jsthis, start+i, &val);
+ if(hres == DISP_E_UNKNOWNNAME) {
hres = S_OK;
- else if(SUCCEEDED(hres))
- hres = jsdisp_propput_idx(ret_array, i, &v, ei, caller);
+ }else if(SUCCEEDED(hres)) {
+ hres = jsdisp_propput_idx(ret_array, i, val);
+ jsval_release(val);
+ }
}
- if(SUCCEEDED(hres)) {
- V_VT(&v) = VT_I4;
- V_I4(&v) = delete_cnt;
-
- hres = jsdisp_propput_name(ret_array, lengthW, &v, ei, caller);
- }
+ if(SUCCEEDED(hres))
+ hres = jsdisp_propput_name(ret_array, lengthW, jsval_number(delete_cnt));
}
if(add_args < delete_cnt) {
for(i = start; SUCCEEDED(hres) && i < length-delete_cnt; i++) {
- hres = jsdisp_get_idx(jsthis, i+delete_cnt, &v, ei, caller);
- if(hres == DISP_E_UNKNOWNNAME)
+ hres = jsdisp_get_idx(jsthis, i+delete_cnt, &val);
+ if(hres == DISP_E_UNKNOWNNAME) {
hres = jsdisp_delete_idx(jsthis, i+add_args);
- else if(SUCCEEDED(hres))
- hres = jsdisp_propput_idx(jsthis, i+add_args, &v, ei, caller);
+ }else if(SUCCEEDED(hres)) {
+ hres = jsdisp_propput_idx(jsthis, i+add_args, val);
+ jsval_release(val);
+ }
}
for(i=length; SUCCEEDED(hres) && i != length-delete_cnt+add_args; i--)
hres = jsdisp_delete_idx(jsthis, i-1);
}else if(add_args > delete_cnt) {
for(i=length-delete_cnt; SUCCEEDED(hres) && i != start; i--) {
- hres = jsdisp_get_idx(jsthis, i+delete_cnt-1, &v, ei, caller);
- if(hres == DISP_E_UNKNOWNNAME)
+ hres = jsdisp_get_idx(jsthis, i+delete_cnt-1, &val);
+ if(hres == DISP_E_UNKNOWNNAME) {
hres = jsdisp_delete_idx(jsthis, i+add_args-1);
- else if(SUCCEEDED(hres))
- hres = jsdisp_propput_idx(jsthis, i+add_args-1, &v, ei, caller);
+ }else if(SUCCEEDED(hres)) {
+ hres = jsdisp_propput_idx(jsthis, i+add_args-1, val);
+ jsval_release(val);
+ }
}
}
for(i=0; SUCCEEDED(hres) && i < add_args; i++)
- hres = jsdisp_propput_idx(jsthis, start+i, get_arg(dp,i+2), ei, caller);
+ hres = jsdisp_propput_idx(jsthis, start+i, argv[i+2]);
- if(SUCCEEDED(hres)) {
- V_VT(&v) = VT_I4;
- V_I4(&v) = length-delete_cnt+add_args;
- hres = jsdisp_propput_name(jsthis, lengthW, &v, ei, caller);
- }
+ if(SUCCEEDED(hres))
+ hres = jsdisp_propput_name(jsthis, lengthW, jsval_number(length-delete_cnt+add_args));
if(FAILED(hres)) {
if(ret_array)
return hres;
}
- if(retv) {
- V_VT(retv) = VT_DISPATCH;
- V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(ret_array);
- }
+ if(r)
+ *r = jsval_obj(ret_array);
return S_OK;
}
/* ECMA-262 3rd Edition 15.4.4.2 */
-static HRESULT Array_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT Array_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
ArrayInstance *array;
array = array_this(jsthis);
if(!array)
- return throw_type_error(ctx, ei, IDS_ARRAY_EXPECTED, NULL);
+ return throw_type_error(ctx, JS_E_ARRAY_EXPECTED, NULL);
- return array_join(ctx, &array->dispex, array->length, default_separatorW, retv, ei, sp);
+ return array_join(ctx, &array->dispex, array->length, default_separatorW, r);
}
-static HRESULT Array_toLocaleString(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT Array_toLocaleString(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
FIXME("\n");
return E_NOTIMPL;
}
/* ECMA-262 3rd Edition 15.4.4.13 */
-static HRESULT Array_unshift(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT Array_unshift(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- DispatchEx *jsthis;
+ jsdisp_t *jsthis;
WCHAR buf[14], *buf_end, *str;
- DWORD argc, i, length;
- VARIANT var;
+ DWORD i, length;
+ jsval_t val;
DISPID id;
HRESULT hres;
TRACE("\n");
- hres = get_length(ctx, vthis, ei, &jsthis, &length);
+ hres = get_length(ctx, vthis, &jsthis, &length);
if(FAILED(hres))
return hres;
- argc = arg_cnt(dp);
if(argc) {
buf_end = buf + sizeof(buf)/sizeof(WCHAR)-1;
*buf_end-- = 0;
hres = jsdisp_get_id(jsthis, str, 0, &id);
if(SUCCEEDED(hres)) {
- hres = jsdisp_propget(jsthis, id, &var, ei, caller);
+ hres = jsdisp_propget(jsthis, id, &val);
if(FAILED(hres))
return hres;
- hres = jsdisp_propput_idx(jsthis, i+argc, &var, ei, caller);
- VariantClear(&var);
+ hres = jsdisp_propput_idx(jsthis, i+argc, val);
+ jsval_release(val);
}else if(hres == DISP_E_UNKNOWNNAME) {
hres = IDispatchEx_DeleteMemberByDispID(vthis->u.dispex, id);
}
}
for(i=0; i<argc; i++) {
- hres = jsdisp_propput_idx(jsthis, i, get_arg(dp,i), ei, caller);
+ hres = jsdisp_propput_idx(jsthis, i, argv[i]);
if(FAILED(hres))
return hres;
}
if(argc) {
length += argc;
- hres = set_length(jsthis, ei, length);
+ hres = set_length(jsthis, length);
if(FAILED(hres))
return hres;
}
- if(retv) {
- if(ctx->version < 2) {
- V_VT(retv) = VT_EMPTY;
- }else {
- V_VT(retv) = VT_I4;
- V_I4(retv) = length;
- }
- }
+ if(r)
+ *r = ctx->version < 2 ? jsval_undefined() : jsval_number(length);
return S_OK;
}
-static HRESULT Array_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT Array_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
TRACE("\n");
switch(flags) {
case INVOKE_FUNC:
- return throw_type_error(ctx, ei, IDS_NOT_FUNC, NULL);
+ return throw_type_error(ctx, JS_E_FUNCTION_EXPECTED, NULL);
case INVOKE_PROPERTYGET:
- return array_join(ctx, jsthis->u.jsdisp, array_from_vdisp(jsthis)->length, default_separatorW, retv, ei, sp);
+ return array_join(ctx, jsthis->u.jsdisp, array_from_vdisp(jsthis)->length, default_separatorW, r);
default:
FIXME("unimplemented flags %x\n", flags);
return E_NOTIMPL;
return S_OK;
}
-static void Array_destructor(DispatchEx *dispex)
+static void Array_destructor(jsdisp_t *dispex)
{
heap_free(dispex);
}
-static void Array_on_put(DispatchEx *dispex, const WCHAR *name)
+static void Array_on_put(jsdisp_t *dispex, const WCHAR *name)
{
ArrayInstance *array = (ArrayInstance*)dispex;
const WCHAR *ptr = name;
Array_on_put
};
-static HRESULT ArrayConstr_value(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static const builtin_prop_t ArrayInst_props[] = {
+ {lengthW, Array_length, 0}
+};
+
+static const builtin_info_t ArrayInst_info = {
+ JSCLASS_ARRAY,
+ {NULL, Array_value, 0},
+ sizeof(ArrayInst_props)/sizeof(*ArrayInst_props),
+ ArrayInst_props,
+ Array_destructor,
+ Array_on_put
+};
+
+static HRESULT ArrayConstr_value(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- DispatchEx *obj;
- VARIANT *arg_var;
+ jsdisp_t *obj;
DWORD i;
HRESULT hres;
switch(flags) {
case DISPATCH_METHOD:
case DISPATCH_CONSTRUCT: {
- if(arg_cnt(dp) == 1 && V_VT((arg_var = get_arg(dp, 0))) == VT_I4) {
- if(V_I4(arg_var) < 0)
- return throw_range_error(ctx, ei, IDS_INVALID_LENGTH, NULL);
+ if(argc == 1 && is_number(argv[0])) {
+ double n = get_number(argv[0]);
+
+ if(n < 0 || !is_int32(n))
+ return throw_range_error(ctx, JS_E_INVALID_LENGTH, NULL);
- hres = create_array(ctx, V_I4(arg_var), &obj);
+ hres = create_array(ctx, n, &obj);
if(FAILED(hres))
return hres;
- V_VT(retv) = VT_DISPATCH;
- V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(obj);
+ *r = jsval_obj(obj);
return S_OK;
}
- hres = create_array(ctx, arg_cnt(dp), &obj);
+ hres = create_array(ctx, argc, &obj);
if(FAILED(hres))
return hres;
- for(i=0; i < arg_cnt(dp); i++) {
- hres = jsdisp_propput_idx(obj, i, get_arg(dp, i), ei, caller);
+ for(i=0; i < argc; i++) {
+ hres = jsdisp_propput_idx(obj, i, argv[i]);
if(FAILED(hres))
break;
}
return hres;
}
- V_VT(retv) = VT_DISPATCH;
- V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(obj);
+ *r = jsval_obj(obj);
break;
}
default:
return S_OK;
}
-static HRESULT alloc_array(script_ctx_t *ctx, DispatchEx *object_prototype, ArrayInstance **ret)
+static HRESULT alloc_array(script_ctx_t *ctx, jsdisp_t *object_prototype, ArrayInstance **ret)
{
ArrayInstance *array;
HRESULT hres;
if(object_prototype)
hres = init_dispex(&array->dispex, ctx, &Array_info, object_prototype);
else
- hres = init_dispex_from_constr(&array->dispex, ctx, &Array_info, ctx->array_constr);
+ hres = init_dispex_from_constr(&array->dispex, ctx, &ArrayInst_info, ctx->array_constr);
if(FAILED(hres)) {
heap_free(array);
return S_OK;
}
-HRESULT create_array_constr(script_ctx_t *ctx, DispatchEx *object_prototype, DispatchEx **ret)
+HRESULT create_array_constr(script_ctx_t *ctx, jsdisp_t *object_prototype, jsdisp_t **ret)
{
ArrayInstance *array;
HRESULT hres;
if(FAILED(hres))
return hres;
- hres = create_builtin_function(ctx, ArrayConstr_value, ArrayW, NULL, PROPF_CONSTR|1, &array->dispex, ret);
+ hres = create_builtin_constructor(ctx, ArrayConstr_value, ArrayW, NULL, PROPF_CONSTR|1, &array->dispex, ret);
jsdisp_release(&array->dispex);
return hres;
}
-HRESULT create_array(script_ctx_t *ctx, DWORD length, DispatchEx **ret)
+HRESULT create_array(script_ctx_t *ctx, DWORD length, jsdisp_t **ret)
{
ArrayInstance *array;
HRESULT hres;
WINE_DEFAULT_DEBUG_CHANNEL(jscript);
typedef struct {
- DispatchEx dispex;
+ jsdisp_t dispex;
- VARIANT_BOOL val;
+ BOOL val;
} BoolInstance;
static const WCHAR toStringW[] = {'t','o','S','t','r','i','n','g',0};
}
/* ECMA-262 3rd Edition 15.6.4.2 */
-static HRESULT Bool_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT Bool_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r)
{
BoolInstance *bool;
TRACE("\n");
if(!(bool = bool_this(jsthis)))
- return throw_type_error(ctx, ei, IDS_NOT_BOOL, NULL);
+ return throw_type_error(ctx, JS_E_BOOLEAN_EXPECTED, NULL);
- if(retv) {
- BSTR val;
-
- if(bool->val) val = SysAllocString(trueW);
- else val = SysAllocString(falseW);
+ if(r) {
+ jsstr_t *val;
+ val = jsstr_alloc(bool->val ? trueW : falseW);
if(!val)
return E_OUTOFMEMORY;
- V_VT(retv) = VT_BSTR;
- V_BSTR(retv) = val;
+ *r = jsval_string(val);
}
return S_OK;
}
/* ECMA-262 3rd Edition 15.6.4.3 */
-static HRESULT Bool_valueOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT Bool_valueOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r)
{
BoolInstance *bool;
TRACE("\n");
if(!(bool = bool_this(jsthis)))
- return throw_type_error(ctx, ei, IDS_NOT_BOOL, NULL);
-
- if(retv) {
- V_VT(retv) = VT_BOOL;
- V_BOOL(retv) = bool->val;
- }
+ return throw_type_error(ctx, JS_E_BOOLEAN_EXPECTED, NULL);
+ if(r)
+ *r = jsval_bool(bool->val);
return S_OK;
}
-static HRESULT Bool_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT Bool_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
TRACE("\n");
switch(flags) {
case INVOKE_FUNC:
- return throw_type_error(ctx, ei, IDS_NOT_FUNC, NULL);
+ return throw_type_error(ctx, JS_E_FUNCTION_EXPECTED, NULL);
default:
FIXME("unimplemented flags %x\n", flags);
return E_NOTIMPL;
NULL
};
-static HRESULT BoolConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static const builtin_info_t BoolInst_info = {
+ JSCLASS_BOOLEAN,
+ {NULL, Bool_value, 0},
+ 0, NULL,
+ NULL,
+ NULL
+};
+
+static HRESULT BoolConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
+ BOOL value = FALSE;
HRESULT hres;
- VARIANT_BOOL value = VARIANT_FALSE;
- if(arg_cnt(dp)) {
- hres = to_boolean(get_arg(dp,0), &value);
+ if(argc) {
+ hres = to_boolean(argv[0], &value);
if(FAILED(hres))
return hres;
}
switch(flags) {
case DISPATCH_CONSTRUCT: {
- DispatchEx *bool;
+ jsdisp_t *bool;
hres = create_bool(ctx, value, &bool);
if(FAILED(hres))
return hres;
- V_VT(retv) = VT_DISPATCH;
- V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(bool);
+ *r = jsval_obj(bool);
return S_OK;
}
case INVOKE_FUNC:
- if(retv) {
- V_VT(retv) = VT_BOOL;
- V_BOOL(retv) = value;
- }
+ if(r)
+ *r = jsval_bool(value);
return S_OK;
default:
return S_OK;
}
-static HRESULT alloc_bool(script_ctx_t *ctx, DispatchEx *object_prototype, BoolInstance **ret)
+static HRESULT alloc_bool(script_ctx_t *ctx, jsdisp_t *object_prototype, BoolInstance **ret)
{
BoolInstance *bool;
HRESULT hres;
if(object_prototype)
hres = init_dispex(&bool->dispex, ctx, &Bool_info, object_prototype);
else
- hres = init_dispex_from_constr(&bool->dispex, ctx, &Bool_info, ctx->bool_constr);
+ hres = init_dispex_from_constr(&bool->dispex, ctx, &BoolInst_info, ctx->bool_constr);
if(FAILED(hres)) {
heap_free(bool);
return S_OK;
}
-HRESULT create_bool_constr(script_ctx_t *ctx, DispatchEx *object_prototype, DispatchEx **ret)
+HRESULT create_bool_constr(script_ctx_t *ctx, jsdisp_t *object_prototype, jsdisp_t **ret)
{
BoolInstance *bool;
HRESULT hres;
if(FAILED(hres))
return hres;
- hres = create_builtin_function(ctx, BoolConstr_value, BooleanW, NULL,
+ hres = create_builtin_constructor(ctx, BoolConstr_value, BooleanW, NULL,
PROPF_CONSTR|1, &bool->dispex, ret);
jsdisp_release(&bool->dispex);
return hres;
}
-HRESULT create_bool(script_ctx_t *ctx, VARIANT_BOOL b, DispatchEx **ret)
+HRESULT create_bool(script_ctx_t *ctx, BOOL b, jsdisp_t **ret)
{
BoolInstance *bool;
HRESULT hres;
--- /dev/null
+/*
+ * Copyright 2011 Jacek Caban for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <math.h>
+#include <assert.h>
+
+#include "jscript.h"
+#include "engine.h"
+
+#include <wine/debug.h>
+
+WINE_DEFAULT_DEBUG_CHANNEL(jscript);
+WINE_DECLARE_DEBUG_CHANNEL(jscript_disas);
+
+typedef struct _statement_ctx_t {
+ unsigned stack_use;
+ BOOL using_scope;
+ BOOL using_except;
+
+ unsigned break_label;
+ unsigned continue_label;
+
+ const labelled_statement_t *labelled_stat;
+
+ struct _statement_ctx_t *next;
+} statement_ctx_t;
+
+typedef struct {
+ parser_ctx_t *parser;
+ bytecode_t *code;
+
+ BOOL from_eval;
+
+ unsigned code_off;
+ unsigned code_size;
+
+ unsigned *labels;
+ unsigned labels_size;
+ unsigned labels_cnt;
+
+ statement_ctx_t *stat_ctx;
+ function_code_t *func;
+
+ variable_declaration_t *var_head;
+ variable_declaration_t *var_tail;
+
+ function_expression_t *func_head;
+ function_expression_t *func_tail;
+} compiler_ctx_t;
+
+static const struct {
+ const char *op_str;
+ instr_arg_type_t arg1_type;
+ instr_arg_type_t arg2_type;
+} instr_info[] = {
+#define X(n,a,b,c) {#n,b,c},
+OP_LIST
+#undef X
+};
+
+static void dump_instr_arg(instr_arg_type_t type, instr_arg_t *arg)
+{
+ switch(type) {
+ case ARG_STR:
+ TRACE_(jscript_disas)("\t%s", debugstr_jsstr(arg->str));
+ break;
+ case ARG_BSTR:
+ TRACE_(jscript_disas)("\t%s", debugstr_wn(arg->bstr, SysStringLen(arg->bstr)));
+ break;
+ case ARG_INT:
+ TRACE_(jscript_disas)("\t%d", arg->uint);
+ break;
+ case ARG_UINT:
+ case ARG_ADDR:
+ TRACE_(jscript_disas)("\t%u", arg->uint);
+ break;
+ case ARG_FUNC:
+ case ARG_NONE:
+ break;
+ DEFAULT_UNREACHABLE;
+ }
+}
+
+static void dump_code(compiler_ctx_t *ctx, unsigned off)
+{
+ instr_t *instr;
+
+ for(instr = ctx->code->instrs+off; instr < ctx->code->instrs+ctx->code_off; instr++) {
+ TRACE_(jscript_disas)("%d:\t%s", (int)(instr-ctx->code->instrs), instr_info[instr->op].op_str);
+ if(instr_info[instr->op].arg1_type == ARG_DBL) {
+ TRACE_(jscript_disas)("\t%lf", instr->u.dbl);
+ }else {
+ dump_instr_arg(instr_info[instr->op].arg1_type, instr->u.arg);
+ dump_instr_arg(instr_info[instr->op].arg2_type, instr->u.arg+1);
+ }
+ TRACE_(jscript_disas)("\n");
+ }
+}
+
+static HRESULT compile_expression(compiler_ctx_t*,expression_t*,BOOL);
+static HRESULT compile_statement(compiler_ctx_t*,statement_ctx_t*,statement_t*);
+
+static inline void *compiler_alloc(bytecode_t *code, size_t size)
+{
+ return heap_pool_alloc(&code->heap, size);
+}
+
+static jsstr_t *compiler_alloc_string_len(compiler_ctx_t *ctx, const WCHAR *str, unsigned len)
+{
+ jsstr_t *new_str;
+
+ if(!ctx->code->str_pool_size) {
+ ctx->code->str_pool = heap_alloc(8 * sizeof(jsstr_t*));
+ if(!ctx->code->str_pool)
+ return NULL;
+ ctx->code->str_pool_size = 8;
+ }else if(ctx->code->str_pool_size == ctx->code->str_cnt) {
+ jsstr_t **new_pool;
+
+ new_pool = heap_realloc(ctx->code->str_pool, ctx->code->str_pool_size*2*sizeof(jsstr_t*));
+ if(!new_pool)
+ return NULL;
+
+ ctx->code->str_pool = new_pool;
+ ctx->code->str_pool_size *= 2;
+ }
+
+ new_str = jsstr_alloc_len(str, len);
+ if(!new_str)
+ return NULL;
+
+ ctx->code->str_pool[ctx->code->str_cnt++] = new_str;
+ return new_str;
+}
+
+static jsstr_t *compiler_alloc_string(compiler_ctx_t *ctx, const WCHAR *str)
+{
+ return compiler_alloc_string_len(ctx, str, strlenW(str));
+}
+
+static BOOL ensure_bstr_slot(compiler_ctx_t *ctx)
+{
+ if(!ctx->code->bstr_pool_size) {
+ ctx->code->bstr_pool = heap_alloc(8 * sizeof(BSTR));
+ if(!ctx->code->bstr_pool)
+ return FALSE;
+ ctx->code->bstr_pool_size = 8;
+ }else if(ctx->code->bstr_pool_size == ctx->code->bstr_cnt) {
+ BSTR *new_pool;
+
+ new_pool = heap_realloc(ctx->code->bstr_pool, ctx->code->bstr_pool_size*2*sizeof(BSTR));
+ if(!new_pool)
+ return FALSE;
+
+ ctx->code->bstr_pool = new_pool;
+ ctx->code->bstr_pool_size *= 2;
+ }
+
+ return TRUE;
+}
+
+static BSTR compiler_alloc_bstr(compiler_ctx_t *ctx, const WCHAR *str)
+{
+ if(!ensure_bstr_slot(ctx))
+ return NULL;
+
+ ctx->code->bstr_pool[ctx->code->bstr_cnt] = SysAllocString(str);
+ if(!ctx->code->bstr_pool[ctx->code->bstr_cnt])
+ return NULL;
+
+ return ctx->code->bstr_pool[ctx->code->bstr_cnt++];
+}
+
+static BSTR compiler_alloc_bstr_len(compiler_ctx_t *ctx, const WCHAR *str, size_t len)
+{
+ if(!ensure_bstr_slot(ctx))
+ return NULL;
+
+ ctx->code->bstr_pool[ctx->code->bstr_cnt] = SysAllocStringLen(str, len);
+ if(!ctx->code->bstr_pool[ctx->code->bstr_cnt])
+ return NULL;
+
+ return ctx->code->bstr_pool[ctx->code->bstr_cnt++];
+}
+
+static unsigned push_instr(compiler_ctx_t *ctx, jsop_t op)
+{
+ assert(ctx->code_size >= ctx->code_off);
+
+ if(ctx->code_size == ctx->code_off) {
+ instr_t *new_instrs;
+
+ new_instrs = heap_realloc(ctx->code->instrs, ctx->code_size*2*sizeof(instr_t));
+ if(!new_instrs)
+ return 0;
+
+ ctx->code->instrs = new_instrs;
+ ctx->code_size *= 2;
+ }
+
+ ctx->code->instrs[ctx->code_off].op = op;
+ return ctx->code_off++;
+}
+
+static inline instr_t *instr_ptr(compiler_ctx_t *ctx, unsigned off)
+{
+ assert(off < ctx->code_off);
+ return ctx->code->instrs + off;
+}
+
+static HRESULT push_instr_int(compiler_ctx_t *ctx, jsop_t op, LONG arg)
+{
+ unsigned instr;
+
+ instr = push_instr(ctx, op);
+ if(!instr)
+ return E_OUTOFMEMORY;
+
+ instr_ptr(ctx, instr)->u.arg->lng = arg;
+ return S_OK;
+}
+
+static HRESULT push_instr_str(compiler_ctx_t *ctx, jsop_t op, const WCHAR *arg)
+{
+ unsigned instr;
+ jsstr_t *str;
+
+ str = compiler_alloc_string(ctx, arg);
+ if(!str)
+ return E_OUTOFMEMORY;
+
+ instr = push_instr(ctx, op);
+ if(!instr)
+ return E_OUTOFMEMORY;
+
+ instr_ptr(ctx, instr)->u.arg->str = str;
+ return S_OK;
+}
+
+static HRESULT push_instr_bstr(compiler_ctx_t *ctx, jsop_t op, const WCHAR *arg)
+{
+ unsigned instr;
+ WCHAR *str;
+
+ str = compiler_alloc_bstr(ctx, arg);
+ if(!str)
+ return E_OUTOFMEMORY;
+
+ instr = push_instr(ctx, op);
+ if(!instr)
+ return E_OUTOFMEMORY;
+
+ instr_ptr(ctx, instr)->u.arg->bstr = str;
+ return S_OK;
+}
+
+static HRESULT push_instr_bstr_uint(compiler_ctx_t *ctx, jsop_t op, const WCHAR *arg1, unsigned arg2)
+{
+ unsigned instr;
+ WCHAR *str;
+
+ str = compiler_alloc_bstr(ctx, arg1);
+ if(!str)
+ return E_OUTOFMEMORY;
+
+ instr = push_instr(ctx, op);
+ if(!instr)
+ return E_OUTOFMEMORY;
+
+ instr_ptr(ctx, instr)->u.arg[0].bstr = str;
+ instr_ptr(ctx, instr)->u.arg[1].uint = arg2;
+ return S_OK;
+}
+
+static HRESULT push_instr_uint_str(compiler_ctx_t *ctx, jsop_t op, unsigned arg1, const WCHAR *arg2)
+{
+ unsigned instr;
+ jsstr_t *str;
+
+ str = compiler_alloc_string(ctx, arg2);
+ if(!str)
+ return E_OUTOFMEMORY;
+
+ instr = push_instr(ctx, op);
+ if(!instr)
+ return E_OUTOFMEMORY;
+
+ instr_ptr(ctx, instr)->u.arg[0].uint = arg1;
+ instr_ptr(ctx, instr)->u.arg[1].str = str;
+ return S_OK;
+}
+
+static HRESULT push_instr_double(compiler_ctx_t *ctx, jsop_t op, double arg)
+{
+ unsigned instr;
+
+ instr = push_instr(ctx, op);
+ if(!instr)
+ return E_OUTOFMEMORY;
+
+ instr_ptr(ctx, instr)->u.dbl = arg;
+ return S_OK;
+}
+
+static inline void set_arg_uint(compiler_ctx_t *ctx, unsigned instr, unsigned arg)
+{
+ instr_ptr(ctx, instr)->u.arg->uint = arg;
+}
+
+static HRESULT push_instr_uint(compiler_ctx_t *ctx, jsop_t op, unsigned arg)
+{
+ unsigned instr;
+
+ instr = push_instr(ctx, op);
+ if(!instr)
+ return E_OUTOFMEMORY;
+
+ set_arg_uint(ctx, instr, arg);
+ return S_OK;
+}
+
+static HRESULT compile_binary_expression(compiler_ctx_t *ctx, binary_expression_t *expr, jsop_t op)
+{
+ HRESULT hres;
+
+ hres = compile_expression(ctx, expr->expression1, TRUE);
+ if(FAILED(hres))
+ return hres;
+
+ hres = compile_expression(ctx, expr->expression2, TRUE);
+ if(FAILED(hres))
+ return hres;
+
+ return push_instr(ctx, op) ? S_OK : E_OUTOFMEMORY;
+}
+
+static HRESULT compile_unary_expression(compiler_ctx_t *ctx, unary_expression_t *expr, jsop_t op)
+{
+ HRESULT hres;
+
+ hres = compile_expression(ctx, expr->expression, TRUE);
+ if(FAILED(hres))
+ return hres;
+
+ return push_instr(ctx, op) ? S_OK : E_OUTOFMEMORY;
+}
+
+/* ECMA-262 3rd Edition 11.2.1 */
+static HRESULT compile_member_expression(compiler_ctx_t *ctx, member_expression_t *expr)
+{
+ HRESULT hres;
+
+ hres = compile_expression(ctx, expr->expression, TRUE);
+ if(FAILED(hres))
+ return hres;
+
+ return push_instr_bstr(ctx, OP_member, expr->identifier);
+}
+
+#define LABEL_FLAG 0x80000000
+
+static unsigned alloc_label(compiler_ctx_t *ctx)
+{
+ if(!ctx->labels_size) {
+ ctx->labels = heap_alloc(8 * sizeof(*ctx->labels));
+ if(!ctx->labels)
+ return 0;
+ ctx->labels_size = 8;
+ }else if(ctx->labels_size == ctx->labels_cnt) {
+ unsigned *new_labels;
+
+ new_labels = heap_realloc(ctx->labels, 2*ctx->labels_size*sizeof(*ctx->labels));
+ if(!new_labels)
+ return 0;
+
+ ctx->labels = new_labels;
+ ctx->labels_size *= 2;
+ }
+
+ return ctx->labels_cnt++ | LABEL_FLAG;
+}
+
+static void label_set_addr(compiler_ctx_t *ctx, unsigned label)
+{
+ assert(label & LABEL_FLAG);
+ ctx->labels[label & ~LABEL_FLAG] = ctx->code_off;
+}
+
+static inline BOOL is_memberid_expr(expression_type_t type)
+{
+ return type == EXPR_IDENT || type == EXPR_MEMBER || type == EXPR_ARRAY;
+}
+
+static HRESULT compile_memberid_expression(compiler_ctx_t *ctx, expression_t *expr, unsigned flags)
+{
+ HRESULT hres = S_OK;
+
+ switch(expr->type) {
+ case EXPR_IDENT: {
+ identifier_expression_t *ident_expr = (identifier_expression_t*)expr;
+
+ hres = push_instr_bstr_uint(ctx, OP_identid, ident_expr->identifier, flags);
+ break;
+ }
+ case EXPR_ARRAY: {
+ binary_expression_t *array_expr = (binary_expression_t*)expr;
+
+ hres = compile_expression(ctx, array_expr->expression1, TRUE);
+ if(FAILED(hres))
+ return hres;
+
+ hres = compile_expression(ctx, array_expr->expression2, TRUE);
+ if(FAILED(hres))
+ return hres;
+
+ hres = push_instr_uint(ctx, OP_memberid, flags);
+ break;
+ }
+ case EXPR_MEMBER: {
+ member_expression_t *member_expr = (member_expression_t*)expr;
+
+ hres = compile_expression(ctx, member_expr->expression, TRUE);
+ if(FAILED(hres))
+ return hres;
+
+ /* FIXME: Potential optimization */
+ hres = push_instr_str(ctx, OP_str, member_expr->identifier);
+ if(FAILED(hres))
+ return hres;
+
+ hres = push_instr_uint(ctx, OP_memberid, flags);
+ break;
+ }
+ DEFAULT_UNREACHABLE;
+ }
+
+ return hres;
+}
+
+static HRESULT compile_increment_expression(compiler_ctx_t *ctx, unary_expression_t *expr, jsop_t op, int n)
+{
+ HRESULT hres;
+
+ if(!is_memberid_expr(expr->expression->type)) {
+ hres = compile_expression(ctx, expr->expression, TRUE);
+ if(FAILED(hres))
+ return hres;
+
+ return push_instr_uint(ctx, OP_throw_ref, JS_E_ILLEGAL_ASSIGN);
+ }
+
+ hres = compile_memberid_expression(ctx, expr->expression, fdexNameEnsure);
+ if(FAILED(hres))
+ return hres;
+
+ return push_instr_int(ctx, op, n);
+}
+
+/* ECMA-262 3rd Edition 11.14 */
+static HRESULT compile_comma_expression(compiler_ctx_t *ctx, binary_expression_t *expr, BOOL emit_ret)
+{
+ HRESULT hres;
+
+ hres = compile_expression(ctx, expr->expression1, FALSE);
+ if(FAILED(hres))
+ return hres;
+
+ return compile_expression(ctx, expr->expression2, emit_ret);
+}
+
+/* ECMA-262 3rd Edition 11.11 */
+static HRESULT compile_logical_expression(compiler_ctx_t *ctx, binary_expression_t *expr, jsop_t op)
+{
+ unsigned instr;
+ HRESULT hres;
+
+ hres = compile_expression(ctx, expr->expression1, TRUE);
+ if(FAILED(hres))
+ return hres;
+
+ instr = push_instr(ctx, op);
+ if(!instr)
+ return E_OUTOFMEMORY;
+
+ hres = compile_expression(ctx, expr->expression2, TRUE);
+ if(FAILED(hres))
+ return hres;
+
+ set_arg_uint(ctx, instr, ctx->code_off);
+ return S_OK;
+}
+
+/* ECMA-262 3rd Edition 11.12 */
+static HRESULT compile_conditional_expression(compiler_ctx_t *ctx, conditional_expression_t *expr)
+{
+ unsigned jmp_false, jmp_end;
+ HRESULT hres;
+
+ hres = compile_expression(ctx, expr->expression, TRUE);
+ if(FAILED(hres))
+ return hres;
+
+ jmp_false = push_instr(ctx, OP_cnd_z);
+ if(!jmp_false)
+ return E_OUTOFMEMORY;
+
+ hres = compile_expression(ctx, expr->true_expression, TRUE);
+ if(FAILED(hres))
+ return hres;
+
+ jmp_end = push_instr(ctx, OP_jmp);
+ if(!jmp_end)
+ return E_OUTOFMEMORY;
+
+ set_arg_uint(ctx, jmp_false, ctx->code_off);
+ hres = push_instr_uint(ctx, OP_pop, 1);
+ if(FAILED(hres))
+ return hres;
+
+ hres = compile_expression(ctx, expr->false_expression, TRUE);
+ if(FAILED(hres))
+ return hres;
+
+ set_arg_uint(ctx, jmp_end, ctx->code_off);
+ return S_OK;
+}
+
+static HRESULT compile_new_expression(compiler_ctx_t *ctx, call_expression_t *expr)
+{
+ unsigned arg_cnt = 0;
+ argument_t *arg;
+ HRESULT hres;
+
+ hres = compile_expression(ctx, expr->expression, TRUE);
+ if(FAILED(hres))
+ return hres;
+
+ for(arg = expr->argument_list; arg; arg = arg->next) {
+ hres = compile_expression(ctx, arg->expr, TRUE);
+ if(FAILED(hres))
+ return hres;
+ arg_cnt++;
+ }
+
+ return push_instr_uint(ctx, OP_new, arg_cnt);
+}
+
+static HRESULT compile_call_expression(compiler_ctx_t *ctx, call_expression_t *expr, BOOL emit_ret)
+{
+ unsigned arg_cnt = 0;
+ argument_t *arg;
+ unsigned instr;
+ jsop_t op;
+ HRESULT hres;
+
+ if(is_memberid_expr(expr->expression->type)) {
+ op = OP_call_member;
+ hres = compile_memberid_expression(ctx, expr->expression, 0);
+ }else {
+ op = OP_call;
+ hres = compile_expression(ctx, expr->expression, TRUE);
+ }
+
+ if(FAILED(hres))
+ return hres;
+
+ for(arg = expr->argument_list; arg; arg = arg->next) {
+ hres = compile_expression(ctx, arg->expr, TRUE);
+ if(FAILED(hres))
+ return hres;
+ arg_cnt++;
+ }
+
+ instr = push_instr(ctx, op);
+ if(!instr)
+ return E_OUTOFMEMORY;
+
+ instr_ptr(ctx, instr)->u.arg[0].uint = arg_cnt;
+ instr_ptr(ctx, instr)->u.arg[1].lng = emit_ret;
+ return S_OK;
+}
+
+static HRESULT compile_delete_expression(compiler_ctx_t *ctx, unary_expression_t *expr)
+{
+ HRESULT hres;
+
+ switch(expr->expression->type) {
+ case EXPR_ARRAY: {
+ binary_expression_t *array_expr = (binary_expression_t*)expr->expression;
+
+ hres = compile_expression(ctx, array_expr->expression1, TRUE);
+ if(FAILED(hres))
+ return hres;
+
+ hres = compile_expression(ctx, array_expr->expression2, TRUE);
+ if(FAILED(hres))
+ return hres;
+
+ if(!push_instr(ctx, OP_delete))
+ return E_OUTOFMEMORY;
+ break;
+ }
+ case EXPR_MEMBER: {
+ member_expression_t *member_expr = (member_expression_t*)expr->expression;
+
+ hres = compile_expression(ctx, member_expr->expression, TRUE);
+ if(FAILED(hres))
+ return hres;
+
+ /* FIXME: Potential optimization */
+ hres = push_instr_str(ctx, OP_str, member_expr->identifier);
+ if(FAILED(hres))
+ return hres;
+
+ if(!push_instr(ctx, OP_delete))
+ return E_OUTOFMEMORY;
+ break;
+ }
+ case EXPR_IDENT:
+ return push_instr_bstr(ctx, OP_delete_ident, ((identifier_expression_t*)expr->expression)->identifier);
+ default: {
+ const WCHAR fixmeW[] = {'F','I','X','M','E',0};
+
+ WARN("invalid delete, unimplemented exception message\n");
+
+ hres = compile_expression(ctx, expr->expression, TRUE);
+ if(FAILED(hres))
+ return hres;
+
+ return push_instr_uint_str(ctx, OP_throw_type, JS_E_INVALID_DELETE, fixmeW);
+ }
+ }
+
+ return S_OK;
+}
+
+static HRESULT compile_assign_expression(compiler_ctx_t *ctx, binary_expression_t *expr, jsop_t op)
+{
+ BOOL use_throw_path = FALSE;
+ unsigned arg_cnt = 0;
+ HRESULT hres;
+
+ if(expr->expression1->type == EXPR_CALL) {
+ call_expression_t *call_expr = (call_expression_t*)expr->expression1;
+ argument_t *arg;
+
+ if(op != OP_LAST) {
+ FIXME("op %d not supported on parametrized assign expressions\n", op);
+ return E_NOTIMPL;
+ }
+
+ if(is_memberid_expr(call_expr->expression->type) && call_expr->argument_list) {
+ hres = compile_memberid_expression(ctx, call_expr->expression, fdexNameEnsure);
+ if(FAILED(hres))
+ return hres;
+
+ for(arg = call_expr->argument_list; arg; arg = arg->next) {
+ hres = compile_expression(ctx, arg->expr, TRUE);
+ if(FAILED(hres))
+ return hres;
+ arg_cnt++;
+ }
+ }else {
+ use_throw_path = TRUE;
+ }
+ }else if(is_memberid_expr(expr->expression1->type)) {
+ hres = compile_memberid_expression(ctx, expr->expression1, fdexNameEnsure);
+ if(FAILED(hres))
+ return hres;
+ }else {
+ use_throw_path = TRUE;
+ }
+
+ if(use_throw_path) {
+ /* Illegal assignment: evaluate and throw */
+ hres = compile_expression(ctx, expr->expression1, TRUE);
+ if(FAILED(hres))
+ return hres;
+
+ hres = compile_expression(ctx, expr->expression2, TRUE);
+ if(FAILED(hres))
+ return hres;
+
+ if(op != OP_LAST && !push_instr(ctx, op))
+ return E_OUTOFMEMORY;
+
+ return push_instr_uint(ctx, OP_throw_ref, JS_E_ILLEGAL_ASSIGN);
+ }
+
+ if(op != OP_LAST && !push_instr(ctx, OP_refval))
+ return E_OUTOFMEMORY;
+
+ hres = compile_expression(ctx, expr->expression2, TRUE);
+ if(FAILED(hres))
+ return hres;
+
+ if(op != OP_LAST && !push_instr(ctx, op))
+ return E_OUTOFMEMORY;
+
+ if(arg_cnt)
+ return push_instr_uint(ctx, OP_assign_call, arg_cnt);
+
+ if(!push_instr(ctx, OP_assign))
+ return E_OUTOFMEMORY;
+
+ return S_OK;
+}
+
+static HRESULT compile_typeof_expression(compiler_ctx_t *ctx, unary_expression_t *expr)
+{
+ jsop_t op;
+ HRESULT hres;
+
+ if(is_memberid_expr(expr->expression->type)) {
+ if(expr->expression->type == EXPR_IDENT)
+ return push_instr_bstr(ctx, OP_typeofident, ((identifier_expression_t*)expr->expression)->identifier);
+
+ op = OP_typeofid;
+ hres = compile_memberid_expression(ctx, expr->expression, 0);
+ }else {
+ op = OP_typeof;
+ hres = compile_expression(ctx, expr->expression, TRUE);
+ }
+ if(FAILED(hres))
+ return hres;
+
+ return push_instr(ctx, op) ? S_OK : E_OUTOFMEMORY;
+}
+
+static HRESULT compile_literal(compiler_ctx_t *ctx, literal_t *literal)
+{
+ switch(literal->type) {
+ case LT_BOOL:
+ return push_instr_int(ctx, OP_bool, literal->u.bval);
+ case LT_DOUBLE:
+ return push_instr_double(ctx, OP_double, literal->u.dval);
+ case LT_NULL:
+ return push_instr(ctx, OP_null) ? S_OK : E_OUTOFMEMORY;
+ case LT_STRING:
+ return push_instr_str(ctx, OP_str, literal->u.wstr);
+ case LT_REGEXP: {
+ unsigned instr;
+ jsstr_t *str;
+
+ str = compiler_alloc_string_len(ctx, literal->u.regexp.str, literal->u.regexp.str_len);
+ if(!str)
+ return E_OUTOFMEMORY;
+
+ instr = push_instr(ctx, OP_regexp);
+ if(!instr)
+ return E_OUTOFMEMORY;
+
+ instr_ptr(ctx, instr)->u.arg[0].str = str;
+ instr_ptr(ctx, instr)->u.arg[1].uint = literal->u.regexp.flags;
+ return S_OK;
+ }
+ DEFAULT_UNREACHABLE;
+ }
+}
+
+static HRESULT literal_as_bstr(compiler_ctx_t *ctx, literal_t *literal, BSTR *str)
+{
+ switch(literal->type) {
+ case LT_STRING:
+ *str = compiler_alloc_bstr(ctx, literal->u.wstr);
+ break;
+ case LT_DOUBLE: {
+ jsstr_t *jsstr;
+ HRESULT hres;
+
+ hres = double_to_string(literal->u.dval, &jsstr);
+ if(FAILED(hres))
+ return hres;
+
+ *str = compiler_alloc_bstr_len(ctx, NULL, jsstr_length(jsstr));
+ if(*str)
+ jsstr_flush(jsstr, *str);
+ jsstr_release(jsstr);
+ break;
+ }
+ DEFAULT_UNREACHABLE;
+ }
+
+ return *str ? S_OK : E_OUTOFMEMORY;
+}
+
+static HRESULT compile_array_literal(compiler_ctx_t *ctx, array_literal_expression_t *expr)
+{
+ unsigned i, elem_cnt = expr->length;
+ array_element_t *iter;
+ HRESULT hres;
+
+ for(iter = expr->element_list; iter; iter = iter->next) {
+ elem_cnt += iter->elision+1;
+
+ for(i=0; i < iter->elision; i++) {
+ if(!push_instr(ctx, OP_undefined))
+ return E_OUTOFMEMORY;
+ }
+
+ hres = compile_expression(ctx, iter->expr, TRUE);
+ if(FAILED(hres))
+ return hres;
+ }
+
+ for(i=0; i < expr->length; i++) {
+ if(!push_instr(ctx, OP_undefined))
+ return E_OUTOFMEMORY;
+ }
+
+ return push_instr_uint(ctx, OP_carray, elem_cnt);
+}
+
+static HRESULT compile_object_literal(compiler_ctx_t *ctx, property_value_expression_t *expr)
+{
+ prop_val_t *iter;
+ unsigned instr;
+ BSTR name;
+ HRESULT hres;
+
+ if(!push_instr(ctx, OP_new_obj))
+ return E_OUTOFMEMORY;
+
+ for(iter = expr->property_list; iter; iter = iter->next) {
+ hres = literal_as_bstr(ctx, iter->name, &name);
+ if(FAILED(hres))
+ return hres;
+
+ hres = compile_expression(ctx, iter->value, TRUE);
+ if(FAILED(hres))
+ return hres;
+
+ instr = push_instr(ctx, OP_obj_prop);
+ if(!instr)
+ return E_OUTOFMEMORY;
+
+ instr_ptr(ctx, instr)->u.arg->bstr = name;
+ }
+
+ return S_OK;
+}
+
+static HRESULT compile_function_expression(compiler_ctx_t *ctx, function_expression_t *expr)
+{
+ ctx->func_tail = ctx->func_tail ? (ctx->func_tail->next = expr) : (ctx->func_head = expr);
+
+ /* FIXME: not exactly right */
+ if(expr->identifier) {
+ ctx->func->func_cnt++;
+ return push_instr_bstr(ctx, OP_ident, expr->identifier);
+ }
+
+ return push_instr_uint(ctx, OP_func, ctx->func->func_cnt++);
+}
+
+static HRESULT compile_expression(compiler_ctx_t *ctx, expression_t *expr, BOOL emit_ret)
+{
+ HRESULT hres;
+
+ switch(expr->type) {
+ case EXPR_ADD:
+ hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_add);
+ break;
+ case EXPR_AND:
+ hres = compile_logical_expression(ctx, (binary_expression_t*)expr, OP_cnd_z);
+ break;
+ case EXPR_ARRAY:
+ hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_array);
+ break;
+ case EXPR_ARRAYLIT:
+ hres = compile_array_literal(ctx, (array_literal_expression_t*)expr);
+ break;
+ case EXPR_ASSIGN:
+ hres = compile_assign_expression(ctx, (binary_expression_t*)expr, OP_LAST);
+ break;
+ case EXPR_ASSIGNADD:
+ hres = compile_assign_expression(ctx, (binary_expression_t*)expr, OP_add);
+ break;
+ case EXPR_ASSIGNAND:
+ hres = compile_assign_expression(ctx, (binary_expression_t*)expr, OP_and);
+ break;
+ case EXPR_ASSIGNSUB:
+ hres = compile_assign_expression(ctx, (binary_expression_t*)expr, OP_sub);
+ break;
+ case EXPR_ASSIGNMUL:
+ hres = compile_assign_expression(ctx, (binary_expression_t*)expr, OP_mul);
+ break;
+ case EXPR_ASSIGNDIV:
+ hres = compile_assign_expression(ctx, (binary_expression_t*)expr, OP_div);
+ break;
+ case EXPR_ASSIGNMOD:
+ hres = compile_assign_expression(ctx, (binary_expression_t*)expr, OP_mod);
+ break;
+ case EXPR_ASSIGNOR:
+ hres = compile_assign_expression(ctx, (binary_expression_t*)expr, OP_or);
+ break;
+ case EXPR_ASSIGNLSHIFT:
+ hres = compile_assign_expression(ctx, (binary_expression_t*)expr, OP_lshift);
+ break;
+ case EXPR_ASSIGNRSHIFT:
+ hres = compile_assign_expression(ctx, (binary_expression_t*)expr, OP_rshift);
+ break;
+ case EXPR_ASSIGNRRSHIFT:
+ hres = compile_assign_expression(ctx, (binary_expression_t*)expr, OP_rshift2);
+ break;
+ case EXPR_ASSIGNXOR:
+ hres = compile_assign_expression(ctx, (binary_expression_t*)expr, OP_xor);
+ break;
+ case EXPR_BAND:
+ hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_and);
+ break;
+ case EXPR_BITNEG:
+ hres = compile_unary_expression(ctx, (unary_expression_t*)expr, OP_bneg);
+ break;
+ case EXPR_BOR:
+ hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_or);
+ break;
+ case EXPR_CALL:
+ return compile_call_expression(ctx, (call_expression_t*)expr, emit_ret);
+ case EXPR_COMMA:
+ return compile_comma_expression(ctx, (binary_expression_t*)expr, emit_ret);
+ case EXPR_COND:
+ hres = compile_conditional_expression(ctx, (conditional_expression_t*)expr);
+ break;
+ case EXPR_DELETE:
+ hres = compile_delete_expression(ctx, (unary_expression_t*)expr);
+ break;
+ case EXPR_DIV:
+ hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_div);
+ break;
+ case EXPR_EQ:
+ hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_eq);
+ break;
+ case EXPR_EQEQ:
+ hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_eq2);
+ break;
+ case EXPR_FUNC:
+ hres = compile_function_expression(ctx, (function_expression_t*)expr);
+ break;
+ case EXPR_GREATER:
+ hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_gt);
+ break;
+ case EXPR_GREATEREQ:
+ hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_gteq);
+ break;
+ case EXPR_IDENT:
+ hres = push_instr_bstr(ctx, OP_ident, ((identifier_expression_t*)expr)->identifier);
+ break;
+ case EXPR_IN:
+ hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_in);
+ break;
+ case EXPR_INSTANCEOF:
+ hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_instanceof);
+ break;
+ case EXPR_LESS:
+ hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_lt);
+ break;
+ case EXPR_LESSEQ:
+ hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_lteq);
+ break;
+ case EXPR_LITERAL:
+ hres = compile_literal(ctx, ((literal_expression_t*)expr)->literal);
+ break;
+ case EXPR_LOGNEG:
+ hres = compile_unary_expression(ctx, (unary_expression_t*)expr, OP_neg);
+ break;
+ case EXPR_LSHIFT:
+ hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_lshift);
+ break;
+ case EXPR_MEMBER:
+ hres = compile_member_expression(ctx, (member_expression_t*)expr);
+ break;
+ case EXPR_MINUS:
+ hres = compile_unary_expression(ctx, (unary_expression_t*)expr, OP_minus);
+ break;
+ case EXPR_MOD:
+ hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_mod);
+ break;
+ case EXPR_MUL:
+ hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_mul);
+ break;
+ case EXPR_NEW:
+ hres = compile_new_expression(ctx, (call_expression_t*)expr);
+ break;
+ case EXPR_NOTEQ:
+ hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_neq);
+ break;
+ case EXPR_NOTEQEQ:
+ hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_neq2);
+ break;
+ case EXPR_OR:
+ hres = compile_logical_expression(ctx, (binary_expression_t*)expr, OP_cnd_nz);
+ break;
+ case EXPR_PLUS:
+ hres = compile_unary_expression(ctx, (unary_expression_t*)expr, OP_tonum);
+ break;
+ case EXPR_POSTDEC:
+ hres = compile_increment_expression(ctx, (unary_expression_t*)expr, OP_postinc, -1);
+ break;
+ case EXPR_POSTINC:
+ hres = compile_increment_expression(ctx, (unary_expression_t*)expr, OP_postinc, 1);
+ break;
+ case EXPR_PREDEC:
+ hres = compile_increment_expression(ctx, (unary_expression_t*)expr, OP_preinc, -1);
+ break;
+ case EXPR_PREINC:
+ hres = compile_increment_expression(ctx, (unary_expression_t*)expr, OP_preinc, 1);
+ break;
+ case EXPR_PROPVAL:
+ hres = compile_object_literal(ctx, (property_value_expression_t*)expr);
+ break;
+ case EXPR_RSHIFT:
+ hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_rshift);
+ break;
+ case EXPR_RRSHIFT:
+ hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_rshift2);
+ break;
+ case EXPR_SUB:
+ hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_sub);
+ break;
+ case EXPR_THIS:
+ return !emit_ret || push_instr(ctx, OP_this) ? S_OK : E_OUTOFMEMORY;
+ case EXPR_TYPEOF:
+ hres = compile_typeof_expression(ctx, (unary_expression_t*)expr);
+ break;
+ case EXPR_VOID:
+ hres = compile_unary_expression(ctx, (unary_expression_t*)expr, OP_void);
+ break;
+ case EXPR_BXOR:
+ hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_xor);
+ break;
+ DEFAULT_UNREACHABLE;
+ }
+
+ if(FAILED(hres))
+ return hres;
+
+ return emit_ret ? S_OK : push_instr_uint(ctx, OP_pop, 1);
+}
+
+static inline BOOL is_loop_statement(statement_type_t type)
+{
+ return type == STAT_FOR || type == STAT_FORIN || type == STAT_WHILE;
+}
+
+/* ECMA-262 3rd Edition 12.1 */
+static HRESULT compile_block_statement(compiler_ctx_t *ctx, statement_t *iter)
+{
+ HRESULT hres;
+
+ while(iter) {
+ hres = compile_statement(ctx, NULL, iter);
+ if(FAILED(hres))
+ return hres;
+
+ iter = iter->next;
+ }
+
+ return S_OK;
+}
+
+/* ECMA-262 3rd Edition 12.2 */
+static HRESULT compile_variable_list(compiler_ctx_t *ctx, variable_declaration_t *list)
+{
+ variable_declaration_t *iter;
+ HRESULT hres;
+
+ assert(list != NULL);
+
+ if(ctx->var_tail)
+ ctx->var_tail->global_next = list;
+ else
+ ctx->var_head = list;
+
+ for(iter = list; iter; iter = iter->next) {
+ ctx->func->var_cnt++;
+ iter->global_next = iter->next;
+ if(!iter->next)
+ ctx->var_tail = iter;
+
+ if(!iter->expr)
+ continue;
+
+ hres = compile_expression(ctx, iter->expr, TRUE);
+ if(FAILED(hres))
+ return hres;
+
+ hres = push_instr_bstr(ctx, OP_var_set, iter->identifier);
+ if(FAILED(hres))
+ return hres;
+ }
+
+ return S_OK;
+}
+
+/* ECMA-262 3rd Edition 12.2 */
+static HRESULT compile_var_statement(compiler_ctx_t *ctx, var_statement_t *stat)
+{
+ return compile_variable_list(ctx, stat->variable_list);
+}
+
+/* ECMA-262 3rd Edition 12.4 */
+static HRESULT compile_expression_statement(compiler_ctx_t *ctx, expression_statement_t *stat)
+{
+ HRESULT hres;
+
+ hres = compile_expression(ctx, stat->expr, ctx->from_eval);
+ if(FAILED(hres))
+ return hres;
+
+ return !ctx->from_eval || push_instr(ctx, OP_setret) ? S_OK : E_OUTOFMEMORY;
+}
+
+/* ECMA-262 3rd Edition 12.5 */
+static HRESULT compile_if_statement(compiler_ctx_t *ctx, if_statement_t *stat)
+{
+ unsigned jmp_else;
+ HRESULT hres;
+
+ hres = compile_expression(ctx, stat->expr, TRUE);
+ if(FAILED(hres))
+ return hres;
+
+ jmp_else = push_instr(ctx, OP_jmp_z);
+ if(!jmp_else)
+ return E_OUTOFMEMORY;
+
+ hres = compile_statement(ctx, NULL, stat->if_stat);
+ if(FAILED(hres))
+ return hres;
+
+ if(stat->else_stat) {
+ unsigned jmp_end;
+
+ jmp_end = push_instr(ctx, OP_jmp);
+ if(!jmp_end)
+ return E_OUTOFMEMORY;
+
+ set_arg_uint(ctx, jmp_else, ctx->code_off);
+
+ hres = compile_statement(ctx, NULL, stat->else_stat);
+ if(FAILED(hres))
+ return hres;
+
+ set_arg_uint(ctx, jmp_end, ctx->code_off);
+ }else {
+ set_arg_uint(ctx, jmp_else, ctx->code_off);
+ }
+
+ return S_OK;
+}
+
+/* ECMA-262 3rd Edition 12.6.2 */
+static HRESULT compile_while_statement(compiler_ctx_t *ctx, while_statement_t *stat)
+{
+ statement_ctx_t stat_ctx = {0, FALSE, FALSE};
+ unsigned jmp_off;
+ HRESULT hres;
+
+ stat_ctx.break_label = alloc_label(ctx);
+ if(!stat_ctx.break_label)
+ return E_OUTOFMEMORY;
+
+ stat_ctx.continue_label = alloc_label(ctx);
+ if(!stat_ctx.continue_label)
+ return E_OUTOFMEMORY;
+
+ jmp_off = ctx->code_off;
+
+ if(!stat->do_while) {
+ label_set_addr(ctx, stat_ctx.continue_label);
+ hres = compile_expression(ctx, stat->expr, TRUE);
+ if(FAILED(hres))
+ return hres;
+
+ hres = push_instr_uint(ctx, OP_jmp_z, stat_ctx.break_label);
+ if(FAILED(hres))
+ return hres;
+ }
+
+ hres = compile_statement(ctx, &stat_ctx, stat->statement);
+ if(FAILED(hres))
+ return hres;
+
+ if(stat->do_while) {
+ label_set_addr(ctx, stat_ctx.continue_label);
+ hres = compile_expression(ctx, stat->expr, TRUE);
+ if(FAILED(hres))
+ return hres;
+
+ hres = push_instr_uint(ctx, OP_jmp_z, stat_ctx.break_label);
+ if(FAILED(hres))
+ return hres;
+ }
+
+ hres = push_instr_uint(ctx, OP_jmp, jmp_off);
+ if(FAILED(hres))
+ return hres;
+
+ label_set_addr(ctx, stat_ctx.break_label);
+ return S_OK;
+}
+
+/* ECMA-262 3rd Edition 12.6.3 */
+static HRESULT compile_for_statement(compiler_ctx_t *ctx, for_statement_t *stat)
+{
+ statement_ctx_t stat_ctx = {0, FALSE, FALSE};
+ unsigned expr_off;
+ HRESULT hres;
+
+ if(stat->variable_list) {
+ hres = compile_variable_list(ctx, stat->variable_list);
+ if(FAILED(hres))
+ return hres;
+ }else if(stat->begin_expr) {
+ hres = compile_expression(ctx, stat->begin_expr, FALSE);
+ if(FAILED(hres))
+ return hres;
+ }
+
+ stat_ctx.break_label = alloc_label(ctx);
+ if(!stat_ctx.break_label)
+ return E_OUTOFMEMORY;
+
+ stat_ctx.continue_label = alloc_label(ctx);
+ if(!stat_ctx.continue_label)
+ return E_OUTOFMEMORY;
+
+ expr_off = ctx->code_off;
+
+ if(stat->expr) {
+ hres = compile_expression(ctx, stat->expr, TRUE);
+ if(FAILED(hres))
+ return hres;
+
+ hres = push_instr_uint(ctx, OP_jmp_z, stat_ctx.break_label);
+ if(FAILED(hres))
+ return hres;
+ }
+
+ hres = compile_statement(ctx, &stat_ctx, stat->statement);
+ if(FAILED(hres))
+ return hres;
+
+ label_set_addr(ctx, stat_ctx.continue_label);
+
+ if(stat->end_expr) {
+ hres = compile_expression(ctx, stat->end_expr, FALSE);
+ if(FAILED(hres))
+ return hres;
+ }
+
+ hres = push_instr_uint(ctx, OP_jmp, expr_off);
+ if(FAILED(hres))
+ return hres;
+
+ label_set_addr(ctx, stat_ctx.break_label);
+ return S_OK;
+}
+
+/* ECMA-262 3rd Edition 12.6.4 */
+static HRESULT compile_forin_statement(compiler_ctx_t *ctx, forin_statement_t *stat)
+{
+ statement_ctx_t stat_ctx = {4, FALSE, FALSE};
+ HRESULT hres;
+
+ if(stat->variable) {
+ hres = compile_variable_list(ctx, stat->variable);
+ if(FAILED(hres))
+ return hres;
+ }
+
+ stat_ctx.break_label = alloc_label(ctx);
+ if(!stat_ctx.break_label)
+ return E_OUTOFMEMORY;
+
+ stat_ctx.continue_label = alloc_label(ctx);
+ if(!stat_ctx.continue_label)
+ return E_OUTOFMEMORY;
+
+ hres = compile_expression(ctx, stat->in_expr, TRUE);
+ if(FAILED(hres))
+ return hres;
+
+ if(stat->variable) {
+ hres = push_instr_bstr_uint(ctx, OP_identid, stat->variable->identifier, fdexNameEnsure);
+ if(FAILED(hres))
+ return hres;
+ }else if(is_memberid_expr(stat->expr->type)) {
+ hres = compile_memberid_expression(ctx, stat->expr, fdexNameEnsure);
+ if(FAILED(hres))
+ return hres;
+ }else {
+ hres = push_instr_uint(ctx, OP_throw_ref, JS_E_ILLEGAL_ASSIGN);
+ if(FAILED(hres))
+ return hres;
+
+ /* FIXME: compile statement anyways when we depend on compiler to check errors */
+ return S_OK;
+ }
+
+ hres = push_instr_int(ctx, OP_int, DISPID_STARTENUM);
+ if(FAILED(hres))
+ return hres;
+
+ label_set_addr(ctx, stat_ctx.continue_label);
+ hres = push_instr_uint(ctx, OP_forin, stat_ctx.break_label);
+ if(FAILED(hres))
+ return E_OUTOFMEMORY;
+
+ hres = compile_statement(ctx, &stat_ctx, stat->statement);
+ if(FAILED(hres))
+ return hres;
+
+ hres = push_instr_uint(ctx, OP_jmp, stat_ctx.continue_label);
+ if(FAILED(hres))
+ return hres;
+
+ label_set_addr(ctx, stat_ctx.break_label);
+ return S_OK;
+}
+
+static HRESULT pop_to_stat(compiler_ctx_t *ctx, BOOL var_stack, BOOL scope_stack, statement_ctx_t *stat_ctx)
+{
+ unsigned stack_pop = 0;
+ statement_ctx_t *iter;
+
+ for(iter = ctx->stat_ctx; iter != stat_ctx; iter = iter->next) {
+ if(scope_stack) {
+ if(iter->using_scope && !push_instr(ctx, OP_pop_scope))
+ return E_OUTOFMEMORY;
+ if(iter->using_except && !push_instr(ctx, OP_pop_except))
+ return E_OUTOFMEMORY;
+ }
+ stack_pop += iter->stack_use;
+ }
+
+ if(var_stack && stack_pop) {
+ HRESULT hres;
+
+ hres = push_instr_uint(ctx, OP_pop, stack_pop);
+ if(FAILED(hres))
+ return hres;
+ }
+
+ return S_OK;
+}
+
+/* ECMA-262 3rd Edition 12.7 */
+static HRESULT compile_continue_statement(compiler_ctx_t *ctx, branch_statement_t *stat)
+{
+ statement_ctx_t *pop_ctx;
+ HRESULT hres;
+
+ if(stat->identifier) {
+ statement_t *label_stat;
+ statement_ctx_t *iter;
+
+ pop_ctx = NULL;
+
+ for(iter = ctx->stat_ctx; iter; iter = iter->next) {
+ if(iter->continue_label)
+ pop_ctx = iter;
+ if(iter->labelled_stat && !strcmpW(iter->labelled_stat->identifier, stat->identifier))
+ break;
+ }
+
+ if(!iter) {
+ WARN("Label not found\n");
+ return JS_E_LABEL_NOT_FOUND;
+ }
+
+ /* Labelled continue are allowed only on loops */
+ for(label_stat = iter->labelled_stat->statement;
+ label_stat->type == STAT_LABEL;
+ label_stat = ((labelled_statement_t*)label_stat)->statement);
+ if(!is_loop_statement(label_stat->type)) {
+ WARN("Label is not a loop\n");
+ return JS_E_INVALID_CONTINUE;
+ }
+
+ assert(pop_ctx != NULL);
+ }else {
+ for(pop_ctx = ctx->stat_ctx; pop_ctx; pop_ctx = pop_ctx->next) {
+ if(pop_ctx->continue_label)
+ break;
+ }
+
+ if(!pop_ctx) {
+ WARN("continue outside loop\n");
+ return JS_E_INVALID_CONTINUE;
+ }
+ }
+
+ hres = pop_to_stat(ctx, TRUE, TRUE, pop_ctx);
+ if(FAILED(hres))
+ return hres;
+
+ return push_instr_uint(ctx, OP_jmp, pop_ctx->continue_label);
+}
+
+/* ECMA-262 3rd Edition 12.8 */
+static HRESULT compile_break_statement(compiler_ctx_t *ctx, branch_statement_t *stat)
+{
+ statement_ctx_t *pop_ctx;
+ HRESULT hres;
+
+ if(stat->identifier) {
+ for(pop_ctx = ctx->stat_ctx; pop_ctx; pop_ctx = pop_ctx->next) {
+ if(pop_ctx->labelled_stat && !strcmpW(pop_ctx->labelled_stat->identifier, stat->identifier)) {
+ assert(pop_ctx->break_label);
+ break;
+ }
+ }
+
+ if(!pop_ctx) {
+ WARN("Label not found\n");
+ return JS_E_LABEL_NOT_FOUND;
+ }
+ }else {
+ for(pop_ctx = ctx->stat_ctx; pop_ctx; pop_ctx = pop_ctx->next) {
+ if(pop_ctx->break_label && !pop_ctx->labelled_stat)
+ break;
+ }
+
+ if(!pop_ctx) {
+ WARN("Break outside loop\n");
+ return JS_E_INVALID_BREAK;
+ }
+ }
+
+ hres = pop_to_stat(ctx, TRUE, TRUE, pop_ctx->next);
+ if(FAILED(hres))
+ return hres;
+
+ return push_instr_uint(ctx, OP_jmp, pop_ctx->break_label);
+}
+
+/* ECMA-262 3rd Edition 12.9 */
+static HRESULT compile_return_statement(compiler_ctx_t *ctx, expression_statement_t *stat)
+{
+ HRESULT hres;
+
+ if(ctx->from_eval) {
+ WARN("misplaced return statement\n");
+ return JS_E_MISPLACED_RETURN;
+ }
+
+ hres = pop_to_stat(ctx, TRUE, FALSE, NULL);
+ if(FAILED(hres))
+ return hres;
+
+ if(stat->expr) {
+ hres = compile_expression(ctx, stat->expr, TRUE);
+ if(FAILED(hres))
+ return hres;
+ if(!push_instr(ctx, OP_setret))
+ return E_OUTOFMEMORY;
+ }
+
+ hres = pop_to_stat(ctx, FALSE, TRUE, NULL);
+ if(FAILED(hres))
+ return hres;
+
+ return push_instr(ctx, OP_ret) ? S_OK : E_OUTOFMEMORY;
+}
+
+/* ECMA-262 3rd Edition 12.10 */
+static HRESULT compile_with_statement(compiler_ctx_t *ctx, with_statement_t *stat)
+{
+ statement_ctx_t stat_ctx = {0, TRUE, FALSE};
+ HRESULT hres;
+
+ hres = compile_expression(ctx, stat->expr, TRUE);
+ if(FAILED(hres))
+ return hres;
+
+ if(!push_instr(ctx, OP_push_scope))
+ return E_OUTOFMEMORY;
+
+ hres = compile_statement(ctx, &stat_ctx, stat->statement);
+ if(FAILED(hres))
+ return hres;
+
+ if(!push_instr(ctx, OP_pop_scope))
+ return E_OUTOFMEMORY;
+
+ return S_OK;
+}
+
+/* ECMA-262 3rd Edition 12.10 */
+static HRESULT compile_labelled_statement(compiler_ctx_t *ctx, labelled_statement_t *stat)
+{
+ statement_ctx_t stat_ctx = {0, FALSE, FALSE, 0, 0, stat}, *iter;
+ HRESULT hres;
+
+ for(iter = ctx->stat_ctx; iter; iter = iter->next) {
+ if(iter->labelled_stat && !strcmpW(iter->labelled_stat->identifier, stat->identifier)) {
+ WARN("Label %s redefined\n", debugstr_w(stat->identifier));
+ return JS_E_LABEL_REDEFINED;
+ }
+ }
+
+ /* Labelled breaks are allowed for any labelled statements, not only loops (violating spec) */
+ stat_ctx.break_label = alloc_label(ctx);
+ if(!stat_ctx.break_label)
+ return E_OUTOFMEMORY;
+
+ hres = compile_statement(ctx, &stat_ctx, stat->statement);
+ if(FAILED(hres))
+ return hres;
+
+ label_set_addr(ctx, stat_ctx.break_label);
+ return S_OK;
+}
+
+/* ECMA-262 3rd Edition 12.13 */
+static HRESULT compile_switch_statement(compiler_ctx_t *ctx, switch_statement_t *stat)
+{
+ statement_ctx_t stat_ctx = {0, FALSE, FALSE};
+ unsigned case_cnt = 0, *case_jmps, i, default_jmp;
+ BOOL have_default = FALSE;
+ statement_t *stat_iter;
+ case_clausule_t *iter;
+ HRESULT hres;
+
+ hres = compile_expression(ctx, stat->expr, TRUE);
+ if(FAILED(hres))
+ return hres;
+
+ stat_ctx.break_label = alloc_label(ctx);
+ if(!stat_ctx.break_label)
+ return E_OUTOFMEMORY;
+
+ for(iter = stat->case_list; iter; iter = iter->next) {
+ if(iter->expr)
+ case_cnt++;
+ }
+
+ case_jmps = heap_alloc(case_cnt * sizeof(*case_jmps));
+ if(!case_jmps)
+ return E_OUTOFMEMORY;
+
+ i = 0;
+ for(iter = stat->case_list; iter; iter = iter->next) {
+ if(!iter->expr) {
+ have_default = TRUE;
+ continue;
+ }
+
+ hres = compile_expression(ctx, iter->expr, TRUE);
+ if(FAILED(hres))
+ break;
+
+ case_jmps[i] = push_instr(ctx, OP_case);
+ if(!case_jmps[i]) {
+ hres = E_OUTOFMEMORY;
+ break;
+ }
+ i++;
+ }
+
+ if(SUCCEEDED(hres)) {
+ hres = push_instr_uint(ctx, OP_pop, 1);
+ if(SUCCEEDED(hres)) {
+ default_jmp = push_instr(ctx, OP_jmp);
+ if(!default_jmp)
+ hres = E_OUTOFMEMORY;
+ }
+ }
+
+ if(FAILED(hres)) {
+ heap_free(case_jmps);
+ return hres;
+ }
+
+ i = 0;
+ for(iter = stat->case_list; iter; iter = iter->next) {
+ while(iter->next && iter->next->stat == iter->stat) {
+ set_arg_uint(ctx, iter->expr ? case_jmps[i++] : default_jmp, ctx->code_off);
+ iter = iter->next;
+ }
+
+ set_arg_uint(ctx, iter->expr ? case_jmps[i++] : default_jmp, ctx->code_off);
+
+ for(stat_iter = iter->stat; stat_iter && (!iter->next || iter->next->stat != stat_iter);
+ stat_iter = stat_iter->next) {
+ hres = compile_statement(ctx, &stat_ctx, stat_iter);
+ if(FAILED(hres))
+ break;
+ }
+ if(FAILED(hres))
+ break;
+ }
+
+ heap_free(case_jmps);
+ if(FAILED(hres))
+ return hres;
+ assert(i == case_cnt);
+
+ if(!have_default) {
+ hres = push_instr_uint(ctx, OP_jmp, stat_ctx.break_label);
+ if(FAILED(hres))
+ return hres;
+ set_arg_uint(ctx, default_jmp, ctx->code_off);
+ }
+
+ label_set_addr(ctx, stat_ctx.break_label);
+ return S_OK;
+}
+
+/* ECMA-262 3rd Edition 12.13 */
+static HRESULT compile_throw_statement(compiler_ctx_t *ctx, expression_statement_t *stat)
+{
+ HRESULT hres;
+
+ hres = compile_expression(ctx, stat->expr, TRUE);
+ if(FAILED(hres))
+ return hres;
+
+ return push_instr(ctx, OP_throw) ? S_OK : E_OUTOFMEMORY;
+}
+
+/* ECMA-262 3rd Edition 12.14 */
+static HRESULT compile_try_statement(compiler_ctx_t *ctx, try_statement_t *stat)
+{
+ statement_ctx_t try_ctx = {0, FALSE, TRUE}, catch_ctx = {0, TRUE, FALSE};
+ statement_ctx_t finally_ctx = {2, FALSE, FALSE};
+ unsigned push_except;
+ BSTR ident;
+ HRESULT hres;
+
+ push_except = push_instr(ctx, OP_push_except);
+ if(!push_except)
+ return E_OUTOFMEMORY;
+
+ if(stat->catch_block) {
+ ident = compiler_alloc_bstr(ctx, stat->catch_block->identifier);
+ if(!ident)
+ return E_OUTOFMEMORY;
+ }else {
+ ident = NULL;
+ }
+
+ instr_ptr(ctx, push_except)->u.arg[1].bstr = ident;
+
+ if(!stat->catch_block)
+ try_ctx.stack_use = 2;
+
+ hres = compile_statement(ctx, &try_ctx, stat->try_statement);
+ if(FAILED(hres))
+ return hres;
+
+ if(!push_instr(ctx, OP_pop_except))
+ return E_OUTOFMEMORY;
+
+ if(stat->catch_block) {
+ unsigned jmp_finally;
+
+ jmp_finally = push_instr(ctx, OP_jmp);
+ if(!jmp_finally)
+ return E_OUTOFMEMORY;
+
+ instr_ptr(ctx, push_except)->u.arg[0].uint = ctx->code_off;
+
+ hres = compile_statement(ctx, &catch_ctx, stat->catch_block->statement);
+ if(FAILED(hres))
+ return hres;
+
+ if(!push_instr(ctx, OP_pop_scope))
+ return E_OUTOFMEMORY;
+
+ set_arg_uint(ctx, jmp_finally, ctx->code_off);
+ }else {
+ set_arg_uint(ctx, push_except, ctx->code_off);
+ }
+
+ if(stat->finally_statement) {
+ hres = compile_statement(ctx, stat->catch_block ? NULL : &finally_ctx, stat->finally_statement);
+ if(FAILED(hres))
+ return hres;
+
+ if(!stat->catch_block && !push_instr(ctx, OP_end_finally))
+ return E_OUTOFMEMORY;
+ }
+
+ return S_OK;
+}
+
+static HRESULT compile_statement(compiler_ctx_t *ctx, statement_ctx_t *stat_ctx, statement_t *stat)
+{
+ HRESULT hres;
+
+ if(stat_ctx) {
+ stat_ctx->next = ctx->stat_ctx;
+ ctx->stat_ctx = stat_ctx;
+ }
+
+ switch(stat->type) {
+ case STAT_BLOCK:
+ hres = compile_block_statement(ctx, ((block_statement_t*)stat)->stat_list);
+ break;
+ case STAT_BREAK:
+ hres = compile_break_statement(ctx, (branch_statement_t*)stat);
+ break;
+ case STAT_CONTINUE:
+ hres = compile_continue_statement(ctx, (branch_statement_t*)stat);
+ break;
+ case STAT_EMPTY:
+ /* nothing to do */
+ hres = S_OK;
+ break;
+ case STAT_EXPR:
+ hres = compile_expression_statement(ctx, (expression_statement_t*)stat);
+ break;
+ case STAT_FOR:
+ hres = compile_for_statement(ctx, (for_statement_t*)stat);
+ break;
+ case STAT_FORIN:
+ hres = compile_forin_statement(ctx, (forin_statement_t*)stat);
+ break;
+ case STAT_IF:
+ hres = compile_if_statement(ctx, (if_statement_t*)stat);
+ break;
+ case STAT_LABEL:
+ hres = compile_labelled_statement(ctx, (labelled_statement_t*)stat);
+ break;
+ case STAT_RETURN:
+ hres = compile_return_statement(ctx, (expression_statement_t*)stat);
+ break;
+ case STAT_SWITCH:
+ hres = compile_switch_statement(ctx, (switch_statement_t*)stat);
+ break;
+ case STAT_THROW:
+ hres = compile_throw_statement(ctx, (expression_statement_t*)stat);
+ break;
+ case STAT_TRY:
+ hres = compile_try_statement(ctx, (try_statement_t*)stat);
+ break;
+ case STAT_VAR:
+ hres = compile_var_statement(ctx, (var_statement_t*)stat);
+ break;
+ case STAT_WHILE:
+ hres = compile_while_statement(ctx, (while_statement_t*)stat);
+ break;
+ case STAT_WITH:
+ hres = compile_with_statement(ctx, (with_statement_t*)stat);
+ break;
+ DEFAULT_UNREACHABLE;
+ }
+
+ if(stat_ctx) {
+ assert(ctx->stat_ctx == stat_ctx);
+ ctx->stat_ctx = stat_ctx->next;
+ }
+
+ return hres;
+}
+
+static void resolve_labels(compiler_ctx_t *ctx, unsigned off)
+{
+ instr_t *instr;
+
+ for(instr = ctx->code->instrs+off; instr < ctx->code->instrs+ctx->code_off; instr++) {
+ if(instr_info[instr->op].arg1_type == ARG_ADDR && (instr->u.arg->uint & LABEL_FLAG)) {
+ assert((instr->u.arg->uint & ~LABEL_FLAG) < ctx->labels_cnt);
+ instr->u.arg->uint = ctx->labels[instr->u.arg->uint & ~LABEL_FLAG];
+ }
+ assert(instr_info[instr->op].arg2_type != ARG_ADDR);
+ }
+
+ ctx->labels_cnt = 0;
+}
+
+void release_bytecode(bytecode_t *code)
+{
+ unsigned i;
+
+ if(--code->ref)
+ return;
+
+ for(i=0; i < code->bstr_cnt; i++)
+ SysFreeString(code->bstr_pool[i]);
+ for(i=0; i < code->str_cnt; i++)
+ jsstr_release(code->str_pool[i]);
+
+ heap_free(code->source);
+ heap_pool_free(&code->heap);
+ heap_free(code->bstr_pool);
+ heap_free(code->str_pool);
+ heap_free(code->instrs);
+ heap_free(code);
+}
+
+static HRESULT init_code(compiler_ctx_t *compiler, const WCHAR *source)
+{
+ compiler->code = heap_alloc_zero(sizeof(bytecode_t));
+ if(!compiler->code)
+ return E_OUTOFMEMORY;
+
+ compiler->code->ref = 1;
+ heap_pool_init(&compiler->code->heap);
+
+ compiler->code->source = heap_strdupW(source);
+ if(!compiler->code->source) {
+ release_bytecode(compiler->code);
+ return E_OUTOFMEMORY;
+ }
+
+ compiler->code->instrs = heap_alloc(64 * sizeof(instr_t));
+ if(!compiler->code->instrs) {
+ release_bytecode(compiler->code);
+ return E_OUTOFMEMORY;
+ }
+
+ compiler->code_size = 64;
+ compiler->code_off = 1;
+ return S_OK;
+}
+
+static HRESULT compile_function(compiler_ctx_t *ctx, source_elements_t *source, function_expression_t *func_expr,
+ BOOL from_eval, function_code_t *func)
+{
+ variable_declaration_t *var_iter;
+ function_expression_t *iter;
+ unsigned off, i;
+ HRESULT hres;
+
+ TRACE("\n");
+
+ ctx->var_head = ctx->var_tail = NULL;
+ ctx->func_head = ctx->func_tail = NULL;
+ ctx->from_eval = from_eval;
+
+ off = ctx->code_off;
+ ctx->func = func;
+ hres = compile_block_statement(ctx, source->statement);
+ if(FAILED(hres))
+ return hres;
+
+ resolve_labels(ctx, off);
+
+ if(!push_instr(ctx, OP_ret))
+ return E_OUTOFMEMORY;
+
+ if(TRACE_ON(jscript_disas))
+ dump_code(ctx, off);
+
+ func->instr_off = off;
+
+ if(func_expr && func_expr->identifier) {
+ func->name = compiler_alloc_bstr(ctx, func_expr->identifier);
+ if(!func->name)
+ return E_OUTOFMEMORY;
+ }
+
+ if(func_expr) {
+ parameter_t *param_iter;
+
+ func->source = func_expr->src_str;
+ func->source_len = func_expr->src_len;
+
+ for(param_iter = func_expr->parameter_list; param_iter; param_iter = param_iter->next)
+ func->param_cnt++;
+
+ func->params = compiler_alloc(ctx->code, func->param_cnt * sizeof(*func->params));
+ if(!func->params)
+ return E_OUTOFMEMORY;
+
+ for(param_iter = func_expr->parameter_list, i=0; param_iter; param_iter = param_iter->next, i++) {
+ func->params[i] = compiler_alloc_bstr(ctx, param_iter->identifier);
+ if(!func->params[i])
+ return E_OUTOFMEMORY;
+ }
+ }
+
+ func->variables = compiler_alloc(ctx->code, func->var_cnt * sizeof(*func->variables));
+ if(!func->variables)
+ return E_OUTOFMEMORY;
+
+ for(var_iter = ctx->var_head, i=0; var_iter; var_iter = var_iter->global_next, i++) {
+ func->variables[i] = compiler_alloc_bstr(ctx, var_iter->identifier);
+ if(!func->variables[i])
+ return E_OUTOFMEMORY;
+ }
+
+ assert(i == func->var_cnt);
+
+ func->funcs = compiler_alloc(ctx->code, func->func_cnt * sizeof(*func->funcs));
+ if(!func->funcs)
+ return E_OUTOFMEMORY;
+ memset(func->funcs, 0, func->func_cnt * sizeof(*func->funcs));
+
+ for(iter = ctx->func_head, i=0; iter; iter = iter->next, i++) {
+ hres = compile_function(ctx, iter->source_elements, iter, FALSE, func->funcs+i);
+ if(FAILED(hres))
+ return hres;
+ }
+
+ assert(i == func->func_cnt);
+
+ return S_OK;
+}
+
+static HRESULT parse_arguments(compiler_ctx_t *ctx, const WCHAR *args, BSTR *arg_array, unsigned *args_size)
+{
+ const WCHAR *ptr = args, *ptr2;
+ unsigned arg_cnt = 0;
+
+ while(isspaceW(*ptr))
+ ptr++;
+ if(!*ptr) {
+ if(args_size)
+ *args_size = 0;
+ return S_OK;
+ }
+
+ while(1) {
+ if(!isalphaW(*ptr) && *ptr != '_') {
+ FIXME("expected alpha or '_': %s\n", debugstr_w(ptr));
+ return E_FAIL;
+ }
+
+ ptr2 = ptr;
+ while(isalnumW(*ptr) || *ptr == '_')
+ ptr++;
+
+ if(*ptr && *ptr != ',' && !isspaceW(*ptr)) {
+ FIXME("unexpected har %s\n", debugstr_w(ptr));
+ return E_FAIL;
+ }
+
+ if(arg_array) {
+ arg_array[arg_cnt] = compiler_alloc_bstr_len(ctx, ptr2, ptr-ptr2);
+ if(!arg_array[arg_cnt])
+ return E_OUTOFMEMORY;
+ }
+ arg_cnt++;
+
+ while(isspaceW(*ptr))
+ ptr++;
+ if(!*ptr)
+ break;
+ if(*ptr != ',') {
+ FIXME("expected ',': %s\n", debugstr_w(ptr));
+ return E_FAIL;
+ }
+
+ ptr++;
+ while(isspaceW(*ptr))
+ ptr++;
+ }
+
+ if(args_size)
+ *args_size = arg_cnt;
+ return S_OK;
+}
+
+static HRESULT compile_arguments(compiler_ctx_t *ctx, const WCHAR *args)
+{
+ HRESULT hres;
+
+ hres = parse_arguments(ctx, args, NULL, &ctx->code->global_code.param_cnt);
+ if(FAILED(hres))
+ return hres;
+
+ ctx->code->global_code.params = compiler_alloc(ctx->code,
+ ctx->code->global_code.param_cnt * sizeof(*ctx->code->global_code.params));
+ if(!ctx->code->global_code.params)
+ return E_OUTOFMEMORY;
+
+ return parse_arguments(ctx, args, ctx->code->global_code.params, NULL);
+}
+
+HRESULT compile_script(script_ctx_t *ctx, const WCHAR *code, const WCHAR *args, const WCHAR *delimiter,
+ BOOL from_eval, BOOL use_decode, bytecode_t **ret)
+{
+ compiler_ctx_t compiler = {0};
+ HRESULT hres;
+
+ hres = init_code(&compiler, code);
+ if(FAILED(hres))
+ return hres;
+
+ if(args) {
+ hres = compile_arguments(&compiler, args);
+ if(FAILED(hres))
+ return hres;
+ }
+
+ if(use_decode) {
+ hres = decode_source(compiler.code->source);
+ if(FAILED(hres)) {
+ WARN("Decoding failed\n");
+ return hres;
+ }
+ }
+
+ hres = script_parse(ctx, compiler.code->source, delimiter, from_eval, &compiler.parser);
+ if(FAILED(hres)) {
+ release_bytecode(compiler.code);
+ return hres;
+ }
+
+ hres = compile_function(&compiler, compiler.parser->source, NULL, from_eval, &compiler.code->global_code);
+ parser_release(compiler.parser);
+ if(FAILED(hres)) {
+ release_bytecode(compiler.code);
+ return hres;
+ }
+
+ *ret = compiler.code;
+ return S_OK;
+}
//#include <limits.h>
//#include <math.h>
+#include <assert.h>
#include "jscript.h"
#define TIME_EPOCH ((ULONGLONG)(369 * 365 + 89) * 86400 * 1000)
typedef struct {
- DispatchEx dispex;
+ jsdisp_t dispex;
/* ECMA-262 3rd Edition 15.9.1.1 */
DOUBLE time;
static const WCHAR setFullYearW[] = {'s','e','t','F','u','l','l','Y','e','a','r',0};
static const WCHAR setUTCFullYearW[] = {'s','e','t','U','T','C','F','u','l','l','Y','e','a','r',0};
static const WCHAR getYearW[] = {'g','e','t','Y','e','a','r',0};
+static const WCHAR setYearW[] = {'s','e','t','Y','e','a','r',0};
static const WCHAR UTCW[] = {'U','T','C',0};
static const WCHAR parseW[] = {'p','a','r','s','e',0};
int y;
if(year != (int)year)
- return ret_nan();
+ return NAN;
y = year;
if(y%4 != 0) return 365;
static inline DOUBLE day_from_year(DOUBLE year)
{
if(year != (int)year)
- return ret_nan();
+ return NAN;
return floor(365.0*(year-1970) + floor((year-1969)/4)
- floor((year-1901)/100) + floor((year-1601)/400));
int y;
if(isnan(time))
- return ret_nan();
+ return NAN;
y = 1970 + time/365.25/MS_PER_DAY;
int dwy = day_within_year(time);
if(isnan(time))
- return ret_nan();
+ return NAN;
if(0<=dwy && dwy<31) return 0;
if(dwy < 59+ily) return 1;
int mft = month_from_time(time);
if(isnan(time))
- return ret_nan();
+ return NAN;
if(mft==0) return dwy+1;
if(mft==1) return dwy-30;
DOUBLE ret;
if(isnan(time))
- return ret_nan();
+ return NAN;
ret = fmod(day(time)+4, 7);
if(ret<0) ret += 7;
int set_week_day;
if(st.wMonth == 0)
- return ret_nan();
+ return NAN;
if(st.wYear != 0)
year = st.wYear;
DOUBLE ret;
if(isnan(time))
- return ret_nan();
+ return NAN;
ret = fmod(floor(time/MS_PER_HOUR), 24);
if(ret<0) ret += 24;
DOUBLE ret;
if(isnan(time))
- return ret_nan();
+ return NAN;
ret = fmod(floor(time/MS_PER_MINUTE), 60);
if(ret<0) ret += 60;
DOUBLE ret;
if(isnan(time))
- return ret_nan();
+ return NAN;
ret = fmod(floor(time/1000), 60);
if(ret<0) ret += 60;
DOUBLE ret;
if(isnan(time))
- return ret_nan();
+ return NAN;
ret = fmod(time, 1000);
if(ret<0) ret += 1000;
static inline DOUBLE time_clip(DOUBLE time)
{
if(8.64e15 < time || time < -8.64e15) {
- return ret_nan();
+ return NAN;
}
return floor(time);
return st;
}
-static inline HRESULT date_to_string(DOUBLE time, BOOL show_offset, int offset, VARIANT *retv)
+static inline HRESULT date_to_string(DOUBLE time, BOOL show_offset, int offset, jsval_t *r)
{
- static const WCHAR NaNW[] = { 'N','a','N',0 };
static const WCHAR formatW[] = { '%','s',' ','%','s',' ','%','d',' ',
'%','0','2','d',':','%','0','2','d',':','%','0','2','d',' ',
'U','T','C','%','c','%','0','2','d','%','0','2','d',' ','%','d','%','s',0 };
LOCALE_SABBREVMONTHNAME11, LOCALE_SABBREVMONTHNAME12 };
BOOL formatAD = TRUE;
- BSTR week, month;
- BSTR date_str;
+ WCHAR week[64], month[64];
+ jsstr_t *date_str;
int len, size, year, day;
- DWORD lcid_en, week_id, month_id;
+ DWORD lcid_en;
WCHAR sign = '-';
if(isnan(time)) {
- if(retv) {
- V_VT(retv) = VT_BSTR;
- V_BSTR(retv) = SysAllocString(NaNW);
- if(!V_BSTR(retv))
- return E_OUTOFMEMORY;
- }
+ if(r)
+ *r = jsval_string(jsstr_nan());
return S_OK;
}
- if(retv) {
+ if(r) {
len = 21;
lcid_en = MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT);
- week_id = week_ids[(int)week_day(time)];
- size = GetLocaleInfoW(lcid_en, week_id, NULL, 0);
- week = SysAllocStringLen(NULL, size);
- if(!week)
- return E_OUTOFMEMORY;
- GetLocaleInfoW(lcid_en, week_id, week, size);
+ size = GetLocaleInfoW(lcid_en, week_ids[(int)week_day(time)], week, sizeof(week)/sizeof(*week));
+ assert(size);
len += size-1;
- month_id = month_ids[(int)month_from_time(time)];
- size = GetLocaleInfoW(lcid_en, month_id, NULL, 0);
- month = SysAllocStringLen(NULL, size);
- if(!month) {
- SysFreeString(week);
- return E_OUTOFMEMORY;
- }
- GetLocaleInfoW(lcid_en, month_id, month, size);
+ size = GetLocaleInfoW(lcid_en, month_ids[(int)month_from_time(time)], month, sizeof(month)/sizeof(*month));
len += size-1;
year = year_from_time(time);
offset = -offset;
}
- date_str = SysAllocStringLen(NULL, len);
- if(!date_str) {
- SysFreeString(week);
- SysFreeString(month);
+ date_str = jsstr_alloc_buf(len);
+ if(!date_str)
return E_OUTOFMEMORY;
- }
if(!show_offset)
- sprintfW(date_str, formatNoOffsetW, week, month, day,
+ sprintfW(date_str->str, formatNoOffsetW, week, month, day,
(int)hour_from_time(time), (int)min_from_time(time),
(int)sec_from_time(time), year, formatAD?ADW:BCW);
else if(offset)
- sprintfW(date_str, formatW, week, month, day,
+ sprintfW(date_str->str, formatW, week, month, day,
(int)hour_from_time(time), (int)min_from_time(time),
(int)sec_from_time(time), sign, offset/60, offset%60,
year, formatAD?ADW:BCW);
else
- sprintfW(date_str, formatUTCW, week, month, day,
+ sprintfW(date_str->str, formatUTCW, week, month, day,
(int)hour_from_time(time), (int)min_from_time(time),
(int)sec_from_time(time), year, formatAD?ADW:BCW);
- SysFreeString(week);
- SysFreeString(month);
-
- V_VT(retv) = VT_BSTR;
- V_BSTR(retv) = date_str;
+ *r = jsval_string(date_str);
}
return S_OK;
}
/* ECMA-262 3rd Edition 15.9.1.2 */
-static HRESULT dateobj_to_string(DateInstance *date, VARIANT *retv)
+static HRESULT dateobj_to_string(DateInstance *date, jsval_t *r)
{
DOUBLE time;
int offset;
offset = date->bias +
daylight_saving_ta(time, date);
- return date_to_string(time, TRUE, offset, retv);
+ return date_to_string(time, TRUE, offset, r);
}
-static HRESULT Date_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT Date_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r)
{
DateInstance *date;
TRACE("\n");
if(!(date = date_this(jsthis)))
- return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
+ return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
- return dateobj_to_string(date, retv);
+ return dateobj_to_string(date, r);
}
/* ECMA-262 3rd Edition 15.9.1.5 */
-static HRESULT Date_toLocaleString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT Date_toLocaleString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- static const WCHAR NaNW[] = { 'N','a','N',0 };
SYSTEMTIME st;
DateInstance *date;
- BSTR date_str;
+ jsstr_t *date_str;
int date_len, time_len;
TRACE("\n");
if(!(date = date_this(jsthis)))
- return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
+ return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
if(isnan(date->time)) {
- if(retv) {
- V_VT(retv) = VT_BSTR;
- V_BSTR(retv) = SysAllocString(NaNW);
- if(!V_BSTR(retv))
- return E_OUTOFMEMORY;
- }
+ if(r)
+ *r = jsval_string(jsstr_nan());
return S_OK;
}
st = create_systemtime(local_time(date->time, date));
if(st.wYear<1601 || st.wYear>9999)
- return dateobj_to_string(date, retv);
+ return dateobj_to_string(date, r);
- if(retv) {
+ if(r) {
date_len = GetDateFormatW(ctx->lcid, DATE_LONGDATE, &st, NULL, NULL, 0);
time_len = GetTimeFormatW(ctx->lcid, 0, &st, NULL, NULL, 0);
- date_str = SysAllocStringLen(NULL, date_len+time_len-1);
+ date_str = jsstr_alloc_buf(date_len+time_len-1);
if(!date_str)
return E_OUTOFMEMORY;
- GetDateFormatW(ctx->lcid, DATE_LONGDATE, &st, NULL, date_str, date_len);
- GetTimeFormatW(ctx->lcid, 0, &st, NULL, &date_str[date_len], time_len);
- date_str[date_len-1] = ' ';
+ GetDateFormatW(ctx->lcid, DATE_LONGDATE, &st, NULL, date_str->str, date_len);
+ GetTimeFormatW(ctx->lcid, 0, &st, NULL, date_str->str+date_len, time_len);
+ date_str->str[date_len-1] = ' ';
- V_VT(retv) = VT_BSTR;
- V_BSTR(retv) = date_str;
+ *r = jsval_string(date_str);
}
return S_OK;
}
-static HRESULT Date_valueOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT Date_valueOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
DateInstance *date;
TRACE("\n");
if(!(date = date_this(jsthis)))
- return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
+ return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
- if(retv)
- num_set_val(retv, date->time);
+ if(r)
+ *r = jsval_number(date->time);
return S_OK;
}
-static inline HRESULT create_utc_string(script_ctx_t *ctx, vdisp_t *jsthis,
- VARIANT *retv, jsexcept_t *ei)
+static inline HRESULT create_utc_string(script_ctx_t *ctx, vdisp_t *jsthis, jsval_t *r)
{
- static const WCHAR NaNW[] = { 'N','a','N',0 };
static const WCHAR formatADW[] = { '%','s',',',' ','%','d',' ','%','s',' ','%','d',' ',
'%','0','2','d',':','%','0','2','d',':','%','0','2','d',' ','U','T','C',0 };
static const WCHAR formatBCW[] = { '%','s',',',' ','%','d',' ','%','s',' ','%','d',' ','B','.','C','.',' ',
LOCALE_SABBREVMONTHNAME11, LOCALE_SABBREVMONTHNAME12 };
BOOL formatAD = TRUE;
- BSTR week, month;
+ WCHAR week[64], month[64];
DateInstance *date;
- BSTR date_str;
+ jsstr_t *date_str;
int len, size, year, day;
- DWORD lcid_en, week_id, month_id;
+ DWORD lcid_en;
if(!(date = date_this(jsthis)))
- return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
+ return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
if(isnan(date->time)) {
- if(retv) {
- V_VT(retv) = VT_BSTR;
- V_BSTR(retv) = SysAllocString(NaNW);
- if(!V_BSTR(retv))
- return E_OUTOFMEMORY;
- }
+ if(r)
+ *r = jsval_string(jsstr_nan());
return S_OK;
}
- if(retv) {
+ if(r) {
len = 17;
lcid_en = MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT);
- week_id = week_ids[(int)week_day(date->time)];
- size = GetLocaleInfoW(lcid_en, week_id, NULL, 0);
- week = SysAllocStringLen(NULL, size);
- if(!week)
- return E_OUTOFMEMORY;
- GetLocaleInfoW(lcid_en, week_id, week, size);
+ size = GetLocaleInfoW(lcid_en, week_ids[(int)week_day(date->time)], week, sizeof(week)/sizeof(*week));
len += size-1;
- month_id = month_ids[(int)month_from_time(date->time)];
- size = GetLocaleInfoW(lcid_en, month_id, NULL, 0);
- month = SysAllocStringLen(NULL, size);
- if(!month) {
- SysFreeString(week);
- return E_OUTOFMEMORY;
- }
- GetLocaleInfoW(lcid_en, month_id, month, size);
+ size = GetLocaleInfoW(lcid_en, month_ids[(int)month_from_time(date->time)], month, sizeof(month)/sizeof(*month));
len += size-1;
year = year_from_time(date->time);
} while(day);
day = date_from_time(date->time);
- date_str = SysAllocStringLen(NULL, len);
- if(!date_str) {
- SysFreeString(week);
- SysFreeString(month);
+ date_str = jsstr_alloc_buf(len);
+ if(!date_str)
return E_OUTOFMEMORY;
- }
- sprintfW(date_str, formatAD?formatADW:formatBCW, week, day, month, year,
+
+ sprintfW(date_str->str, formatAD?formatADW:formatBCW, week, day, month, year,
(int)hour_from_time(date->time), (int)min_from_time(date->time),
(int)sec_from_time(date->time));
- SysFreeString(week);
- SysFreeString(month);
-
- V_VT(retv) = VT_BSTR;
- V_BSTR(retv) = date_str;
+ *r = jsval_string(date_str);
}
return S_OK;
}
/* ECMA-262 3rd Edition 15.9.5.42 */
-static HRESULT Date_toUTCString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT Date_toUTCString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
TRACE("\n");
- return create_utc_string(ctx, jsthis, retv, ei);
+ return create_utc_string(ctx, jsthis, r);
}
-static HRESULT Date_toGMTString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT Date_toGMTString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
TRACE("\n");
- return create_utc_string(ctx, jsthis, retv, ei);
+ return create_utc_string(ctx, jsthis, r);
}
/* ECMA-262 3rd Edition 15.9.5.3 */
-static HRESULT dateobj_to_date_string(DateInstance *date, VARIANT *retv)
+static HRESULT dateobj_to_date_string(DateInstance *date, jsval_t *r)
{
- static const WCHAR NaNW[] = { 'N','a','N',0 };
static const WCHAR formatADW[] = { '%','s',' ','%','s',' ','%','d',' ','%','d',0 };
static const WCHAR formatBCW[] = { '%','s',' ','%','s',' ','%','d',' ','%','d',' ','B','.','C','.',0 };
LOCALE_SABBREVMONTHNAME11, LOCALE_SABBREVMONTHNAME12 };
BOOL formatAD = TRUE;
- BSTR week, month;
- BSTR date_str;
+ WCHAR week[64], month[64];
+ jsstr_t *date_str;
DOUBLE time;
int len, size, year, day;
- DWORD lcid_en, week_id, month_id;
+ DWORD lcid_en;
if(isnan(date->time)) {
- if(retv) {
- V_VT(retv) = VT_BSTR;
- V_BSTR(retv) = SysAllocString(NaNW);
- if(!V_BSTR(retv))
- return E_OUTOFMEMORY;
- }
+ if(r)
+ *r = jsval_string(jsstr_nan());
return S_OK;
}
time = local_time(date->time, date);
- if(retv) {
+ if(r) {
len = 5;
lcid_en = MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT);
- week_id = week_ids[(int)week_day(time)];
- size = GetLocaleInfoW(lcid_en, week_id, NULL, 0);
- week = SysAllocStringLen(NULL, size);
- if(!week)
- return E_OUTOFMEMORY;
- GetLocaleInfoW(lcid_en, week_id, week, size);
+ size = GetLocaleInfoW(lcid_en, week_ids[(int)week_day(time)], week, sizeof(week)/sizeof(*week));
+ assert(size);
len += size-1;
- month_id = month_ids[(int)month_from_time(time)];
- size = GetLocaleInfoW(lcid_en, month_id, NULL, 0);
- month = SysAllocStringLen(NULL, size);
- if(!month) {
- SysFreeString(week);
- return E_OUTOFMEMORY;
- }
- GetLocaleInfoW(lcid_en, month_id, month, size);
+ size = GetLocaleInfoW(lcid_en, month_ids[(int)month_from_time(time)], month, sizeof(month)/sizeof(*month));
+ assert(size);
len += size-1;
year = year_from_time(time);
} while(day);
day = date_from_time(time);
- date_str = SysAllocStringLen(NULL, len);
- if(!date_str) {
- SysFreeString(week);
- SysFreeString(month);
+ date_str = jsstr_alloc_buf(len);
+ if(!date_str)
return E_OUTOFMEMORY;
- }
- sprintfW(date_str, formatAD?formatADW:formatBCW, week, month, day, year);
+ sprintfW(date_str->str, formatAD?formatADW:formatBCW, week, month, day, year);
- SysFreeString(week);
- SysFreeString(month);
-
- V_VT(retv) = VT_BSTR;
- V_BSTR(retv) = date_str;
+ *r = jsval_string(date_str);
}
return S_OK;
}
-static HRESULT Date_toDateString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT Date_toDateString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
DateInstance *date;
if(!(date = date_this(jsthis)))
- return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
+ return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
- return dateobj_to_date_string(date, retv);
+ return dateobj_to_date_string(date, r);
}
/* ECMA-262 3rd Edition 15.9.5.4 */
-static HRESULT Date_toTimeString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT Date_toTimeString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- static const WCHAR NaNW[] = { 'N','a','N',0 };
static const WCHAR formatW[] = { '%','0','2','d',':','%','0','2','d',':','%','0','2','d',
' ','U','T','C','%','c','%','0','2','d','%','0','2','d',0 };
static const WCHAR formatUTCW[] = { '%','0','2','d',':','%','0','2','d',
':','%','0','2','d',' ','U','T','C',0 };
DateInstance *date;
- BSTR date_str;
+ jsstr_t *date_str;
DOUBLE time;
WCHAR sign;
int offset;
TRACE("\n");
if(!(date = date_this(jsthis)))
- return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
+ return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
if(isnan(date->time)) {
- if(retv) {
- V_VT(retv) = VT_BSTR;
- V_BSTR(retv) = SysAllocString(NaNW);
- if(!V_BSTR(retv))
- return E_OUTOFMEMORY;
- }
+ if(r)
+ *r = jsval_string(jsstr_nan());
return S_OK;
}
time = local_time(date->time, date);
- if(retv) {
- date_str = SysAllocStringLen(NULL, 17);
+ if(r) {
+ date_str = jsstr_alloc_buf(17);
if(!date_str)
return E_OUTOFMEMORY;
else sign = '-';
if(offset)
- sprintfW(date_str, formatW, (int)hour_from_time(time),
+ sprintfW(date_str->str, formatW, (int)hour_from_time(time),
(int)min_from_time(time), (int)sec_from_time(time),
sign, offset/60, offset%60);
else
- sprintfW(date_str, formatUTCW, (int)hour_from_time(time),
+ sprintfW(date_str->str, formatUTCW, (int)hour_from_time(time),
(int)min_from_time(time), (int)sec_from_time(time));
- V_VT(retv) = VT_BSTR;
- V_BSTR(retv) = date_str;
+ *r = jsval_string(date_str);
}
return S_OK;
}
/* ECMA-262 3rd Edition 15.9.5.6 */
-static HRESULT Date_toLocaleDateString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT Date_toLocaleDateString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- static const WCHAR NaNW[] = { 'N','a','N',0 };
SYSTEMTIME st;
DateInstance *date;
- BSTR date_str;
+ jsstr_t *date_str;
int len;
TRACE("\n");
if(!(date = date_this(jsthis)))
- return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
+ return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
if(isnan(date->time)) {
- if(retv) {
- V_VT(retv) = VT_BSTR;
- V_BSTR(retv) = SysAllocString(NaNW);
- if(!V_BSTR(retv))
- return E_OUTOFMEMORY;
- }
+ if(r)
+ *r = jsval_string(jsstr_nan());
return S_OK;
}
st = create_systemtime(local_time(date->time, date));
if(st.wYear<1601 || st.wYear>9999)
- return dateobj_to_date_string(date, retv);
+ return dateobj_to_date_string(date, r);
- if(retv) {
+ if(r) {
len = GetDateFormatW(ctx->lcid, DATE_LONGDATE, &st, NULL, NULL, 0);
- date_str = SysAllocStringLen(NULL, len);
+ date_str = jsstr_alloc_buf(len);
if(!date_str)
return E_OUTOFMEMORY;
- GetDateFormatW(ctx->lcid, DATE_LONGDATE, &st, NULL, date_str, len);
+ GetDateFormatW(ctx->lcid, DATE_LONGDATE, &st, NULL, date_str->str, len);
- V_VT(retv) = VT_BSTR;
- V_BSTR(retv) = date_str;
+ *r = jsval_string(date_str);
}
return S_OK;
}
/* ECMA-262 3rd Edition 15.9.5.7 */
-static HRESULT Date_toLocaleTimeString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT Date_toLocaleTimeString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- static const WCHAR NaNW[] = { 'N','a','N',0 };
SYSTEMTIME st;
DateInstance *date;
- BSTR date_str;
+ jsstr_t *date_str;
int len;
TRACE("\n");
if(!(date = date_this(jsthis)))
- return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
+ return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
if(isnan(date->time)) {
- if(retv) {
- V_VT(retv) = VT_BSTR;
- V_BSTR(retv) = SysAllocString(NaNW);
- if(!V_BSTR(retv))
- return E_OUTOFMEMORY;
- }
+ if(r)
+ *r = jsval_string(jsstr_nan());
return S_OK;
}
st = create_systemtime(local_time(date->time, date));
if(st.wYear<1601 || st.wYear>9999)
- return Date_toTimeString(ctx, jsthis, flags, dp, retv, ei, caller);
+ return Date_toTimeString(ctx, jsthis, flags, argc, argv, r);
- if(retv) {
+ if(r) {
len = GetTimeFormatW(ctx->lcid, 0, &st, NULL, NULL, 0);
- date_str = SysAllocStringLen(NULL, len);
+ date_str = jsstr_alloc_buf(len);
if(!date_str)
return E_OUTOFMEMORY;
- GetTimeFormatW(ctx->lcid, 0, &st, NULL, date_str, len);
+ GetTimeFormatW(ctx->lcid, 0, &st, NULL, date_str->str, len);
- V_VT(retv) = VT_BSTR;
- V_BSTR(retv) = date_str;
+ *r = jsval_string(date_str);
}
return S_OK;
}
/* ECMA-262 3rd Edition 15.9.5.9 */
-static HRESULT Date_getTime(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT Date_getTime(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
DateInstance *date;
TRACE("\n");
if(!(date = date_this(jsthis)))
- return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
+ return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
- if(retv)
- num_set_val(retv, date->time);
+ if(r)
+ *r = jsval_number(date->time);
return S_OK;
}
/* ECMA-262 3rd Edition 15.9.5.10 */
-static HRESULT Date_getFullYear(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT Date_getFullYear(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
DateInstance *date;
TRACE("\n");
if(!(date = date_this(jsthis)))
- return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
+ return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
- if(retv) {
+ if(r) {
DOUBLE time = local_time(date->time, date);
- num_set_val(retv, year_from_time(time));
+ *r = jsval_number(year_from_time(time));
}
return S_OK;
}
/* ECMA-262 3rd Edition 15.9.5.11 */
-static HRESULT Date_getUTCFullYear(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT Date_getUTCFullYear(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
DateInstance *date;
TRACE("\n");
if(!(date = date_this(jsthis)))
- return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
+ return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
- if(retv)
- num_set_val(retv, year_from_time(date->time));
+ if(r)
+ *r = jsval_number(year_from_time(date->time));
return S_OK;
}
/* ECMA-262 3rd Edition 15.9.5.12 */
-static HRESULT Date_getMonth(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT Date_getMonth(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r)
{
DateInstance *date;
TRACE("\n");
if(!(date = date_this(jsthis)))
- return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
+ return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
- if(retv) {
- DOUBLE time = local_time(date->time, date);
-
- num_set_val(retv, month_from_time(time));
- }
+ if(r)
+ *r = jsval_number(month_from_time(local_time(date->time, date)));
return S_OK;
}
/* ECMA-262 3rd Edition 15.9.5.13 */
-static HRESULT Date_getUTCMonth(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT Date_getUTCMonth(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
DateInstance *date;
TRACE("\n");
if(!(date = date_this(jsthis)))
- return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
+ return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
- if(retv)
- num_set_val(retv, month_from_time(date->time));
+ if(r)
+ *r = jsval_number(month_from_time(date->time));
return S_OK;
}
/* ECMA-262 3rd Edition 15.9.5.14 */
-static HRESULT Date_getDate(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT Date_getDate(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r)
{
DateInstance *date;
TRACE("\n");
if(!(date = date_this(jsthis)))
- return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
+ return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
- if(retv) {
- DOUBLE time = local_time(date->time, date);
-
- num_set_val(retv, date_from_time(time));
- }
+ if(r)
+ *r = jsval_number(date_from_time(local_time(date->time, date)));
return S_OK;
}
/* ECMA-262 3rd Edition 15.9.5.15 */
-static HRESULT Date_getUTCDate(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT Date_getUTCDate(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
DateInstance *date;
TRACE("\n");
if(!(date = date_this(jsthis)))
- return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
+ return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
- if(retv)
- num_set_val(retv, date_from_time(date->time));
+ if(r)
+ *r = jsval_number(date_from_time(date->time));
return S_OK;
}
/* ECMA-262 3rd Edition 15.9.5.16 */
-static HRESULT Date_getDay(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT Date_getDay(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
DateInstance *date;
TRACE("\n");
if(!(date = date_this(jsthis)))
- return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
-
- if(retv) {
- DOUBLE time = local_time(date->time, date);
+ return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
- num_set_val(retv, week_day(time));
- }
+ if(r)
+ *r = jsval_number(week_day(local_time(date->time, date)));
return S_OK;
}
/* ECMA-262 3rd Edition 15.9.5.17 */
-static HRESULT Date_getUTCDay(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT Date_getUTCDay(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
DateInstance *date;
TRACE("\n");
if(!(date = date_this(jsthis)))
- return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
+ return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
- if(retv)
- num_set_val(retv, week_day(date->time));
+ if(r)
+ *r = jsval_number(week_day(date->time));
return S_OK;
}
/* ECMA-262 3rd Edition 15.9.5.18 */
-static HRESULT Date_getHours(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT Date_getHours(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
DateInstance *date;
TRACE("\n");
if(!(date = date_this(jsthis)))
- return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
+ return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
- if(retv) {
- DOUBLE time = local_time(date->time, date);
-
- num_set_val(retv, hour_from_time(time));
- }
+ if(r)
+ *r = jsval_number(hour_from_time(local_time(date->time, date)));
return S_OK;
}
/* ECMA-262 3rd Edition 15.9.5.19 */
-static HRESULT Date_getUTCHours(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT Date_getUTCHours(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
DateInstance *date;
TRACE("\n");
if(!(date = date_this(jsthis)))
- return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
+ return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
- if(retv)
- num_set_val(retv, hour_from_time(date->time));
+ if(r)
+ *r = jsval_number(hour_from_time(date->time));
return S_OK;
}
/* ECMA-262 3rd Edition 15.9.5.20 */
-static HRESULT Date_getMinutes(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT Date_getMinutes(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
DateInstance *date;
TRACE("\n");
if(!(date = date_this(jsthis)))
- return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
+ return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
- if(retv) {
- DOUBLE time = local_time(date->time, date);
-
- num_set_val(retv, min_from_time(time));
- }
+ if(r)
+ *r = jsval_number(min_from_time(local_time(date->time, date)));
return S_OK;
}
/* ECMA-262 3rd Edition 15.9.5.21 */
-static HRESULT Date_getUTCMinutes(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT Date_getUTCMinutes(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
DateInstance *date;
TRACE("\n");
if(!(date = date_this(jsthis)))
- return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
+ return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
- if(retv)
- num_set_val(retv, min_from_time(date->time));
+ if(r)
+ *r = jsval_number(min_from_time(date->time));
return S_OK;
}
/* ECMA-262 3rd Edition 15.9.5.22 */
-static HRESULT Date_getSeconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT Date_getSeconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r)
{
DateInstance *date;
TRACE("\n");
if(!(date = date_this(jsthis)))
- return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
-
- if(retv) {
- DOUBLE time = local_time(date->time, date);
+ return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
- num_set_val(retv, sec_from_time(time));
- }
+ if(r)
+ *r = jsval_number(sec_from_time(local_time(date->time, date)));
return S_OK;
}
/* ECMA-262 3rd Edition 15.9.5.23 */
-static HRESULT Date_getUTCSeconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT Date_getUTCSeconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
DateInstance *date;
TRACE("\n");
if(!(date = date_this(jsthis)))
- return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
+ return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
- if(retv)
- num_set_val(retv, sec_from_time(date->time));
+ if(r)
+ *r = jsval_number(sec_from_time(date->time));
return S_OK;
}
/* ECMA-262 3rd Edition 15.9.5.24 */
-static HRESULT Date_getMilliseconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT Date_getMilliseconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
DateInstance *date;
TRACE("\n");
if(!(date = date_this(jsthis)))
- return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
+ return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
- if(retv) {
- DOUBLE time = local_time(date->time, date);
-
- num_set_val(retv, ms_from_time(time));
- }
+ if(r)
+ *r = jsval_number(ms_from_time(local_time(date->time, date)));
return S_OK;
}
/* ECMA-262 3rd Edition 15.9.5.25 */
-static HRESULT Date_getUTCMilliseconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT Date_getUTCMilliseconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
DateInstance *date;
TRACE("\n");
if(!(date = date_this(jsthis)))
- return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
+ return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
- if(retv)
- num_set_val(retv, ms_from_time(date->time));
+ if(r)
+ *r = jsval_number(ms_from_time(date->time));
return S_OK;
}
/* ECMA-262 3rd Edition 15.9.5.26 */
-static HRESULT Date_getTimezoneOffset(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT Date_getTimezoneOffset(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
DateInstance *date;
TRACE("\n");
if(!(date = date_this(jsthis)))
- return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
+ return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
- if(retv)
- num_set_val(retv, floor(
- (date->time-local_time(date->time, date))/MS_PER_MINUTE));
+ if(r)
+ *r = jsval_number(floor((date->time-local_time(date->time, date))/MS_PER_MINUTE));
return S_OK;
}
/* ECMA-262 3rd Edition 15.9.5.27 */
-static HRESULT Date_setTime(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT Date_setTime(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- VARIANT v;
+ double n;
HRESULT hres;
DateInstance *date;
TRACE("\n");
if(!(date = date_this(jsthis)))
- return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
+ return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
- if(!arg_cnt(dp))
- return throw_type_error(ctx, ei, IDS_ARG_NOT_OPT, NULL);
+ if(!argc)
+ return throw_type_error(ctx, JS_E_MISSING_ARG, NULL);
- hres = to_number(ctx, get_arg(dp, 0), ei, &v);
+ hres = to_number(ctx, argv[0], &n);
if(FAILED(hres))
return hres;
- date->time = time_clip(num_val(&v));
-
- if(retv)
- num_set_val(retv, date->time);
+ date->time = time_clip(n);
+ if(r)
+ *r = jsval_number(date->time);
return S_OK;
}
/* ECMA-262 3rd Edition 15.9.5.28 */
-static HRESULT Date_setMilliseconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT Date_setMilliseconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- VARIANT v;
- HRESULT hres;
DateInstance *date;
- DOUBLE t;
+ double n, t;
+ HRESULT hres;
TRACE("\n");
if(!(date = date_this(jsthis)))
- return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
+ return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
- if(!arg_cnt(dp))
- return throw_type_error(ctx, ei, IDS_ARG_NOT_OPT, NULL);
+ if(!argc)
+ return throw_type_error(ctx, JS_E_MISSING_ARG, NULL);
- hres = to_number(ctx, get_arg(dp, 0), ei, &v);
+ hres = to_number(ctx, argv[0], &n);
if(FAILED(hres))
return hres;
t = local_time(date->time, date);
t = make_date(day(t), make_time(hour_from_time(t), min_from_time(t),
- sec_from_time(t), num_val(&v)));
+ sec_from_time(t), n));
date->time = time_clip(utc(t, date));
- if(retv)
- num_set_val(retv, date->time);
-
+ if(r)
+ *r = jsval_number(date->time);
return S_OK;
}
/* ECMA-262 3rd Edition 15.9.5.29 */
-static HRESULT Date_setUTCMilliseconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT Date_setUTCMilliseconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- VARIANT v;
- HRESULT hres;
DateInstance *date;
- DOUBLE t;
+ double n, t;
+ HRESULT hres;
TRACE("\n");
if(!(date = date_this(jsthis)))
- return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
+ return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
- if(!arg_cnt(dp))
- return throw_type_error(ctx, ei, IDS_ARG_NOT_OPT, NULL);
+ if(!argc)
+ return throw_type_error(ctx, JS_E_MISSING_ARG, NULL);
- hres = to_number(ctx, get_arg(dp, 0), ei, &v);
+ hres = to_number(ctx, argv[0], &n);
if(FAILED(hres))
return hres;
t = date->time;
t = make_date(day(t), make_time(hour_from_time(t), min_from_time(t),
- sec_from_time(t), num_val(&v)));
+ sec_from_time(t), n));
date->time = time_clip(t);
- if(retv)
- num_set_val(retv, date->time);
-
+ if(r)
+ *r = jsval_number(date->time);
return S_OK;
}
/* ECMA-262 3rd Edition 15.9.5.30 */
-static HRESULT Date_setSeconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT Date_setSeconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- VARIANT v;
- HRESULT hres;
DateInstance *date;
- DOUBLE t, sec, ms;
+ double t, sec, ms;
+ HRESULT hres;
TRACE("\n");
if(!(date = date_this(jsthis)))
- return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
+ return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
- if(!arg_cnt(dp))
- return throw_type_error(ctx, ei, IDS_ARG_NOT_OPT, NULL);
+ if(!argc)
+ return throw_type_error(ctx, JS_E_MISSING_ARG, NULL);
t = local_time(date->time, date);
- hres = to_number(ctx, get_arg(dp, 0), ei, &v);
+ hres = to_number(ctx, argv[0], &sec);
if(FAILED(hres))
return hres;
- sec = num_val(&v);
- if(arg_cnt(dp) > 1) {
- hres = to_number(ctx, get_arg(dp, 1), ei, &v);
+ if(argc > 1) {
+ hres = to_number(ctx, argv[1], &ms);
if(FAILED(hres))
return hres;
- ms = num_val(&v);
+ }else {
+ ms = ms_from_time(t);
}
- else ms = ms_from_time(t);
t = make_date(day(t), make_time(hour_from_time(t),
min_from_time(t), sec, ms));
date->time = time_clip(utc(t, date));
- if(retv)
- num_set_val(retv, date->time);
-
+ if(r)
+ *r = jsval_number(date->time);
return S_OK;
}
/* ECMA-262 3rd Edition 15.9.5.31 */
-static HRESULT Date_setUTCSeconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT Date_setUTCSeconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- VARIANT v;
- HRESULT hres;
DateInstance *date;
- DOUBLE t, sec, ms;
+ double t, sec, ms;
+ HRESULT hres;
TRACE("\n");
if(!(date = date_this(jsthis)))
- return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
+ return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
- if(!arg_cnt(dp))
- return throw_type_error(ctx, ei, IDS_ARG_NOT_OPT, NULL);
+ if(!argc)
+ return throw_type_error(ctx, JS_E_MISSING_ARG, NULL);
t = date->time;
- hres = to_number(ctx, get_arg(dp, 0), ei, &v);
+ hres = to_number(ctx, argv[0], &sec);
if(FAILED(hres))
return hres;
- sec = num_val(&v);
- if(arg_cnt(dp) > 1) {
- hres = to_number(ctx, get_arg(dp, 1), ei, &v);
+ if(argc > 1) {
+ hres = to_number(ctx, argv[1], &ms);
if(FAILED(hres))
return hres;
- ms = num_val(&v);
+ }else {
+ ms = ms_from_time(t);
}
- else ms = ms_from_time(t);
t = make_date(day(t), make_time(hour_from_time(t),
min_from_time(t), sec, ms));
date->time = time_clip(t);
- if(retv)
- num_set_val(retv, date->time);
-
+ if(r)
+ *r = jsval_number(date->time);
return S_OK;
}
/* ECMA-262 3rd Edition 15.9.5.33 */
-static HRESULT Date_setMinutes(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT Date_setMinutes(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- VARIANT v;
- HRESULT hres;
DateInstance *date;
- DOUBLE t, min, sec, ms;
+ double t, min, sec, ms;
+ HRESULT hres;
TRACE("\n");
if(!(date = date_this(jsthis)))
- return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
+ return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
- if(!arg_cnt(dp))
- return throw_type_error(ctx, ei, IDS_ARG_NOT_OPT, NULL);
+ if(!argc)
+ return throw_type_error(ctx, JS_E_MISSING_ARG, NULL);
t = local_time(date->time, date);
- hres = to_number(ctx, get_arg(dp, 0), ei, &v);
+ hres = to_number(ctx, argv[0], &min);
if(FAILED(hres))
return hres;
- min = num_val(&v);
- if(arg_cnt(dp) > 1) {
- hres = to_number(ctx, get_arg(dp, 1), ei, &v);
+ if(argc > 1) {
+ hres = to_number(ctx, argv[1], &sec);
if(FAILED(hres))
return hres;
- sec = num_val(&v);
+ }else {
+ sec = sec_from_time(t);
}
- else sec = sec_from_time(t);
- if(arg_cnt(dp) > 2) {
- hres = to_number(ctx, get_arg(dp, 2), ei, &v);
+ if(argc > 2) {
+ hres = to_number(ctx, argv[2], &ms);
if(FAILED(hres))
return hres;
- ms = num_val(&v);
+ }else {
+ ms = ms_from_time(t);
}
- else ms = ms_from_time(t);
t = make_date(day(t), make_time(hour_from_time(t),
min, sec, ms));
date->time = time_clip(utc(t, date));
- if(retv)
- num_set_val(retv, date->time);
-
+ if(r)
+ *r = jsval_number(date->time);
return S_OK;
}
/* ECMA-262 3rd Edition 15.9.5.34 */
-static HRESULT Date_setUTCMinutes(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT Date_setUTCMinutes(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- VARIANT v;
- HRESULT hres;
DateInstance *date;
- DOUBLE t, min, sec, ms;
+ double t, min, sec, ms;
+ HRESULT hres;
TRACE("\n");
if(!(date = date_this(jsthis)))
- return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
+ return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
- if(!arg_cnt(dp))
- return throw_type_error(ctx, ei, IDS_ARG_NOT_OPT, NULL);
+ if(!argc)
+ return throw_type_error(ctx, JS_E_MISSING_ARG, NULL);
t = date->time;
- hres = to_number(ctx, get_arg(dp, 0), ei, &v);
+ hres = to_number(ctx, argv[0], &min);
if(FAILED(hres))
return hres;
- min = num_val(&v);
- if(arg_cnt(dp) > 1) {
- hres = to_number(ctx, get_arg(dp, 1), ei, &v);
+ if(argc > 1) {
+ hres = to_number(ctx, argv[1], &sec);
if(FAILED(hres))
return hres;
- sec = num_val(&v);
+ }else {
+ sec = sec_from_time(t);
}
- else sec = sec_from_time(t);
- if(arg_cnt(dp) > 2) {
- hres = to_number(ctx, get_arg(dp, 2), ei, &v);
+ if(argc > 2) {
+ hres = to_number(ctx, argv[2], &ms);
if(FAILED(hres))
return hres;
- ms = num_val(&v);
+ }else {
+ ms = ms_from_time(t);
}
- else ms = ms_from_time(t);
t = make_date(day(t), make_time(hour_from_time(t),
min, sec, ms));
date->time = time_clip(t);
- if(retv)
- num_set_val(retv, date->time);
-
+ if(r)
+ *r = jsval_number(date->time);
return S_OK;
}
/* ECMA-262 3rd Edition 15.9.5.35 */
-static HRESULT Date_setHours(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT Date_setHours(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- VARIANT v;
- HRESULT hres;
DateInstance *date;
- DOUBLE t, hour, min, sec, ms;
+ double t, hour, min, sec, ms;
+ HRESULT hres;
TRACE("\n");
if(!(date = date_this(jsthis)))
- return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
+ return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
- if(!arg_cnt(dp))
- return throw_type_error(ctx, ei, IDS_ARG_NOT_OPT, NULL);
+ if(!argc)
+ return throw_type_error(ctx, JS_E_MISSING_ARG, NULL);
t = local_time(date->time, date);
- hres = to_number(ctx, get_arg(dp, 0), ei, &v);
+ hres = to_number(ctx, argv[0], &hour);
if(FAILED(hres))
return hres;
- hour = num_val(&v);
- if(arg_cnt(dp) > 1) {
- hres = to_number(ctx, get_arg(dp, 1), ei, &v);
+ if(argc > 1) {
+ hres = to_number(ctx, argv[1], &min);
if(FAILED(hres))
return hres;
- min = num_val(&v);
+ }else {
+ min = min_from_time(t);
}
- else min = min_from_time(t);
- if(arg_cnt(dp) > 2) {
- hres = to_number(ctx, get_arg(dp, 2), ei, &v);
+ if(argc > 2) {
+ hres = to_number(ctx, argv[2], &sec);
if(FAILED(hres))
return hres;
- sec = num_val(&v);
+ }else {
+ sec = sec_from_time(t);
}
- else sec = sec_from_time(t);
- if(arg_cnt(dp) > 3) {
- hres = to_number(ctx, get_arg(dp, 3), ei, &v);
+ if(argc > 3) {
+ hres = to_number(ctx, argv[3], &ms);
if(FAILED(hres))
return hres;
- ms = num_val(&v);
+ }else {
+ ms = ms_from_time(t);
}
- else ms = ms_from_time(t);
t = make_date(day(t), make_time(hour, min, sec, ms));
date->time = time_clip(utc(t, date));
- if(retv)
- num_set_val(retv, date->time);
-
+ if(r)
+ *r = jsval_number(date->time);
return S_OK;
}
/* ECMA-262 3rd Edition 15.9.5.36 */
-static HRESULT Date_setUTCHours(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT Date_setUTCHours(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
DateInstance *date;
- VARIANT v;
+ double t, hour, min, sec, ms;
HRESULT hres;
- DOUBLE t, hour, min, sec, ms;
TRACE("\n");
if(!(date = date_this(jsthis)))
- return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
+ return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
- if(!arg_cnt(dp))
- return throw_type_error(ctx, ei, IDS_ARG_NOT_OPT, NULL);
+ if(!argc)
+ return throw_type_error(ctx, JS_E_MISSING_ARG, NULL);
t = date->time;
- hres = to_number(ctx, get_arg(dp, 0), ei, &v);
+ hres = to_number(ctx, argv[0], &hour);
if(FAILED(hres))
return hres;
- hour = num_val(&v);
- if(arg_cnt(dp) > 1) {
- hres = to_number(ctx, get_arg(dp, 1), ei, &v);
+ if(argc > 1) {
+ hres = to_number(ctx, argv[1], &min);
if(FAILED(hres))
return hres;
- min = num_val(&v);
+ }else {
+ min = min_from_time(t);
}
- else min = min_from_time(t);
- if(arg_cnt(dp) > 2) {
- hres = to_number(ctx, get_arg(dp, 2), ei, &v);
+ if(argc > 2) {
+ hres = to_number(ctx, argv[2], &sec);
if(FAILED(hres))
return hres;
- sec = num_val(&v);
+ }else {
+ sec = sec_from_time(t);
}
- else sec = sec_from_time(t);
- if(arg_cnt(dp) > 3) {
- hres = to_number(ctx, get_arg(dp, 3), ei, &v);
+ if(argc > 3) {
+ hres = to_number(ctx, argv[3], &ms);
if(FAILED(hres))
return hres;
- ms = num_val(&v);
+ }else {
+ ms = ms_from_time(t);
}
- else ms = ms_from_time(t);
t = make_date(day(t), make_time(hour, min, sec, ms));
date->time = time_clip(t);
- if(retv)
- num_set_val(retv, date->time);
-
+ if(r)
+ *r = jsval_number(date->time);
return S_OK;
}
/* ECMA-262 3rd Edition 15.9.5.36 */
-static HRESULT Date_setDate(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT Date_setDate(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- VARIANT v;
- HRESULT hres;
DateInstance *date;
- DOUBLE t;
+ double t, n;
+ HRESULT hres;
TRACE("\n");
if(!(date = date_this(jsthis)))
- return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
+ return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
- if(!arg_cnt(dp))
- return throw_type_error(ctx, ei, IDS_ARG_NOT_OPT, NULL);
+ if(!argc)
+ return throw_type_error(ctx, JS_E_MISSING_ARG, NULL);
- hres = to_number(ctx, get_arg(dp, 0), ei, &v);
+ hres = to_number(ctx, argv[0], &n);
if(FAILED(hres))
return hres;
t = local_time(date->time, date);
- t = make_date(make_day(year_from_time(t), month_from_time(t),
- num_val(&v)), time_within_day(t));
+ t = make_date(make_day(year_from_time(t), month_from_time(t), n), time_within_day(t));
date->time = time_clip(utc(t, date));
- if(retv)
- num_set_val(retv, date->time);
-
+ if(r)
+ *r = jsval_number(date->time);
return S_OK;
}
/* ECMA-262 3rd Edition 15.9.5.37 */
-static HRESULT Date_setUTCDate(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT Date_setUTCDate(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- VARIANT v;
- HRESULT hres;
DateInstance *date;
- DOUBLE t;
+ double t, n;
+ HRESULT hres;
TRACE("\n");
if(!(date = date_this(jsthis)))
- return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
+ return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
- if(!arg_cnt(dp))
- return throw_type_error(ctx, ei, IDS_ARG_NOT_OPT, NULL);
+ if(!argc)
+ return throw_type_error(ctx, JS_E_MISSING_ARG, NULL);
- hres = to_number(ctx, get_arg(dp, 0), ei, &v);
+ hres = to_number(ctx, argv[0], &n);
if(FAILED(hres))
return hres;
t = date->time;
- t = make_date(make_day(year_from_time(t), month_from_time(t),
- num_val(&v)), time_within_day(t));
+ t = make_date(make_day(year_from_time(t), month_from_time(t), n), time_within_day(t));
date->time = time_clip(t);
- if(retv)
- num_set_val(retv, date->time);
-
+ if(r)
+ *r = jsval_number(date->time);
return S_OK;
}
/* ECMA-262 3rd Edition 15.9.5.38 */
-static HRESULT Date_setMonth(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT Date_setMonth(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- VARIANT v;
- HRESULT hres;
DateInstance *date;
DOUBLE t, month, ddate;
+ HRESULT hres;
TRACE("\n");
if(!(date = date_this(jsthis)))
- return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
+ return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
- if(!arg_cnt(dp))
- return throw_type_error(ctx, ei, IDS_ARG_NOT_OPT, NULL);
+ if(!argc)
+ return throw_type_error(ctx, JS_E_MISSING_ARG, NULL);
t = local_time(date->time, date);
- hres = to_number(ctx, get_arg(dp, 0), ei, &v);
+ hres = to_number(ctx, argv[0], &month);
if(FAILED(hres))
return hres;
- month = num_val(&v);
- if(arg_cnt(dp) > 1) {
- hres = to_number(ctx, get_arg(dp, 1), ei, &v);
+ if(argc > 1) {
+ hres = to_number(ctx, argv[1], &ddate);
if(FAILED(hres))
return hres;
- ddate = num_val(&v);
+ }else {
+ ddate = date_from_time(t);
}
- else ddate = date_from_time(t);
t = make_date(make_day(year_from_time(t), month, ddate),
time_within_day(t));
date->time = time_clip(utc(t, date));
- if(retv)
- num_set_val(retv, date->time);
-
+ if(r)
+ *r = jsval_number(date->time);
return S_OK;
}
/* ECMA-262 3rd Edition 15.9.5.39 */
-static HRESULT Date_setUTCMonth(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT Date_setUTCMonth(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- VARIANT v;
- HRESULT hres;
DateInstance *date;
- DOUBLE t, month, ddate;
+ double t, month, ddate;
+ HRESULT hres;
TRACE("\n");
if(!(date = date_this(jsthis)))
- return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
+ return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
- if(!arg_cnt(dp))
- return throw_type_error(ctx, ei, IDS_ARG_NOT_OPT, NULL);
+ if(!argc)
+ return throw_type_error(ctx, JS_E_MISSING_ARG, NULL);
t = date->time;
- hres = to_number(ctx, get_arg(dp, 0), ei, &v);
+ hres = to_number(ctx, argv[0], &month);
if(FAILED(hres))
return hres;
- month = num_val(&v);
- if(arg_cnt(dp) > 1) {
- hres = to_number(ctx, get_arg(dp, 1), ei, &v);
+ if(argc > 1) {
+ hres = to_number(ctx, argv[1], &ddate);
if(FAILED(hres))
return hres;
- ddate = num_val(&v);
+ }else {
+ ddate = date_from_time(t);
}
- else ddate = date_from_time(t);
t = make_date(make_day(year_from_time(t), month, ddate),
time_within_day(t));
date->time = time_clip(t);
- if(retv)
- num_set_val(retv, date->time);
-
+ if(r)
+ *r = jsval_number(date->time);
return S_OK;
}
/* ECMA-262 3rd Edition 15.9.5.40 */
-static HRESULT Date_setFullYear(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT Date_setFullYear(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- VARIANT v;
- HRESULT hres;
DateInstance *date;
- DOUBLE t, year, month, ddate;
+ double t, year, month, ddate;
+ HRESULT hres;
TRACE("\n");
if(!(date = date_this(jsthis)))
- return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
+ return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
- if(!arg_cnt(dp))
- return throw_type_error(ctx, ei, IDS_ARG_NOT_OPT, NULL);
+ if(!argc)
+ return throw_type_error(ctx, JS_E_MISSING_ARG, NULL);
t = local_time(date->time, date);
- hres = to_number(ctx, get_arg(dp, 0), ei, &v);
+ hres = to_number(ctx, argv[0], &year);
if(FAILED(hres))
return hres;
- year = num_val(&v);
- if(arg_cnt(dp) > 1) {
- hres = to_number(ctx, get_arg(dp, 1), ei, &v);
+ if(argc > 1) {
+ hres = to_number(ctx, argv[1], &month);
if(FAILED(hres))
return hres;
- month = num_val(&v);
+ }else {
+ month = month_from_time(t);
}
- else month = month_from_time(t);
- if(arg_cnt(dp) > 2) {
- hres = to_number(ctx, get_arg(dp, 2), ei, &v);
+ if(argc > 2) {
+ hres = to_number(ctx, argv[2], &ddate);
if(FAILED(hres))
return hres;
- ddate = num_val(&v);
+ }else {
+ ddate = date_from_time(t);
}
- else ddate = date_from_time(t);
t = make_date(make_day(year, month, ddate), time_within_day(t));
date->time = time_clip(utc(t, date));
- if(retv)
- num_set_val(retv, date->time);
-
+ if(r)
+ *r = jsval_number(date->time);
return S_OK;
}
/* ECMA-262 3rd Edition 15.9.5.41 */
-static HRESULT Date_setUTCFullYear(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT Date_setUTCFullYear(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- VARIANT v;
- HRESULT hres;
DateInstance *date;
- DOUBLE t, year, month, ddate;
+ double t, year, month, ddate;
+ HRESULT hres;
TRACE("\n");
if(!(date = date_this(jsthis)))
- return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
+ return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
- if(!arg_cnt(dp))
- return throw_type_error(ctx, ei, IDS_ARG_NOT_OPT, NULL);
+ if(!argc)
+ return throw_type_error(ctx, JS_E_MISSING_ARG, NULL);
t = date->time;
- hres = to_number(ctx, get_arg(dp, 0), ei, &v);
+ hres = to_number(ctx, argv[0], &year);
if(FAILED(hres))
return hres;
- year = num_val(&v);
- if(arg_cnt(dp) > 1) {
- hres = to_number(ctx, get_arg(dp, 1), ei, &v);
+ if(argc > 1) {
+ hres = to_number(ctx, argv[1], &month);
if(FAILED(hres))
return hres;
- month = num_val(&v);
+ }else {
+ month = month_from_time(t);
}
- else month = month_from_time(t);
- if(arg_cnt(dp) > 2) {
- hres = to_number(ctx, get_arg(dp, 2), ei, &v);
+ if(argc > 2) {
+ hres = to_number(ctx, argv[2], &ddate);
if(FAILED(hres))
return hres;
- ddate = num_val(&v);
+ }else {
+ ddate = date_from_time(t);
}
- else ddate = date_from_time(t);
t = make_date(make_day(year, month, ddate), time_within_day(t));
date->time = time_clip(t);
- if(retv)
- num_set_val(retv, date->time);
-
+ if(r)
+ *r = jsval_number(date->time);
return S_OK;
}
/* ECMA-262 3rd Edition B2.4 */
-static HRESULT Date_getYear(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT Date_getYear(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
DateInstance *date;
DOUBLE t, year;
TRACE("\n");
if(!(date = date_this(jsthis)))
- return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
+ return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
t = local_time(date->time, date);
if(isnan(t)) {
- if(retv)
- num_set_nan(retv);
+ if(r)
+ *r = jsval_number(NAN);
return S_OK;
}
year = year_from_time(t);
- if(retv)
- num_set_val(retv, (1900<=year && year<2000)?year-1900:year);
+ if(r)
+ *r = jsval_number((1900<=year && year<2000)?year-1900:year);
+ return S_OK;
+}
+
+/* ECMA-262 3rd Edition B2.5 */
+static HRESULT Date_setYear(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
+{
+ DateInstance *date;
+ DOUBLE t, year;
+ HRESULT hres;
+ TRACE("\n");
+
+ if(!(date = date_this(jsthis)))
+ return throw_type_error(ctx, JS_E_DATE_EXPECTED, NULL);
+
+ if(!argc)
+ return throw_type_error(ctx, JS_E_MISSING_ARG, NULL);
+
+ t = local_time(date->time, date);
+
+ hres = to_number(ctx, argv[0], &year);
+ if(FAILED(hres))
+ return hres;
+
+ if(isnan(year)) {
+ date->time = year;
+ if(r)
+ *r = jsval_number(NAN);
+ return S_OK;
+ }
+
+ year = year >= 0.0 ? floor(year) : -floor(-year);
+ if(-1.0 < year && year < 100.0)
+ year += 1900.0;
+
+ date->time = time_clip(utc(make_date(make_day(year, month_from_time(t), date_from_time(t)), time_within_day(t)), date));
+
+ if(r)
+ *r = jsval_number(date->time);
return S_OK;
}
-static HRESULT Date_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT Date_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
TRACE("\n");
switch(flags) {
case INVOKE_FUNC:
- return throw_type_error(ctx, ei, IDS_NOT_FUNC, NULL);
+ return throw_type_error(ctx, JS_E_FUNCTION_EXPECTED, NULL);
default:
FIXME("unimplemented flags %x\n", flags);
return E_NOTIMPL;
{setUTCMinutesW, Date_setUTCMinutes, PROPF_METHOD|3},
{setUTCMonthW, Date_setUTCMonth, PROPF_METHOD|2},
{setUTCSecondsW, Date_setUTCSeconds, PROPF_METHOD|2},
+ {setYearW, Date_setYear, PROPF_METHOD|1},
{toDateStringW, Date_toDateString, PROPF_METHOD},
{toGMTStringW, Date_toGMTString, PROPF_METHOD},
{toLocaleDateStringW, Date_toLocaleDateString, PROPF_METHOD},
NULL
};
-static HRESULT create_date(script_ctx_t *ctx, DispatchEx *object_prototype, DOUBLE time, DispatchEx **ret)
+static const builtin_info_t DateInst_info = {
+ JSCLASS_DATE,
+ {NULL, Date_value, 0},
+ 0, NULL,
+ NULL,
+ NULL
+};
+
+static HRESULT create_date(script_ctx_t *ctx, jsdisp_t *object_prototype, DOUBLE time, jsdisp_t **ret)
{
DateInstance *date;
HRESULT hres;
if(object_prototype)
hres = init_dispex(&date->dispex, ctx, &Date_info, object_prototype);
else
- hres = init_dispex_from_constr(&date->dispex, ctx, &Date_info, ctx->date_constr);
+ hres = init_dispex_from_constr(&date->dispex, ctx, &DateInst_info, ctx->date_constr);
if(FAILED(hres)) {
heap_free(date);
return hres;
return S_OK;
}
-static inline HRESULT date_parse(BSTR input, VARIANT *retv) {
+static inline HRESULT date_parse(jsstr_t *input_str, double *ret) {
static const DWORD string_ids[] = { LOCALE_SMONTHNAME12, LOCALE_SMONTHNAME11,
LOCALE_SMONTHNAME10, LOCALE_SMONTHNAME9, LOCALE_SMONTHNAME8,
LOCALE_SMONTHNAME7, LOCALE_SMONTHNAME6, LOCALE_SMONTHNAME5,
LOCALE_SMONTHNAME1, LOCALE_SDAYNAME7, LOCALE_SDAYNAME1,
LOCALE_SDAYNAME2, LOCALE_SDAYNAME3, LOCALE_SDAYNAME4,
LOCALE_SDAYNAME5, LOCALE_SDAYNAME6 };
- BSTR strings[sizeof(string_ids)/sizeof(DWORD)];
-
- BSTR parse;
+ WCHAR *strings[sizeof(string_ids)/sizeof(DWORD)];
+ WCHAR *parse;
int input_len, parse_len = 0, nest_level = 0, i, size;
int year = 0, month = 0, day = 0, hour = 0, min = 0, sec = 0;
int ms = 0, offset = 0, hour_adjust = 0;
BOOL set_offset = FALSE, set_era = FALSE, ad = TRUE, set_am = FALSE, am = TRUE;
BOOL set_hour_adjust = TRUE;
TIME_ZONE_INFORMATION tzi;
+ const WCHAR *input;
DateInstance di;
DWORD lcid_en;
- if(retv) num_set_nan(retv);
+ input_len = jsstr_length(input_str);
+ input = input_str->str;
- input_len = SysStringLen(input);
for(i=0; i<input_len; i++) {
if(input[i] == '(') nest_level++;
else if(input[i] == ')') {
nest_level--;
- if(nest_level<0)
+ if(nest_level<0) {
+ *ret = NAN;
return S_OK;
+ }
}
else if(!nest_level) parse_len++;
}
- parse = SysAllocStringLen(NULL, parse_len);
+ parse = heap_alloc((parse_len+1)*sizeof(WCHAR));
if(!parse)
return E_OUTOFMEMORY;
nest_level = 0;
else if(input[i] == ')') nest_level--;
else if(!nest_level) parse[parse_len++] = toupperW(input[i]);
}
+ parse[parse_len] = 0;
GetTimeZoneInformation(&tzi);
di.bias = tzi.Bias;
di.daylightDate = tzi.DaylightDate;
di.daylightBias = tzi.DaylightBias;
+ /* FIXME: Cache strings */
lcid_en = MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT);
for(i=0; i<sizeof(string_ids)/sizeof(DWORD); i++) {
size = GetLocaleInfoW(lcid_en, string_ids[i], NULL, 0);
- strings[i] = SysAllocStringLen(NULL, size);
+ strings[i] = heap_alloc((size+1)*sizeof(WCHAR));
if(!strings[i]) {
i--;
while(i-- >= 0)
- SysFreeString(strings[i]);
- SysFreeString(parse);
+ heap_free(strings[i]);
+ heap_free(parse);
return E_OUTOFMEMORY;
}
GetLocaleInfoW(lcid_en, string_ids[i], strings[i], size);
}
else {
/* Month or garbage */
- int j;
+ unsigned int j;
for(size=i; parse[size]>='A' && parse[size]<='Z'; size++);
size -= i;
for(j=0; j<sizeof(string_ids)/sizeof(DWORD); j++)
- if(!memicmpW(&parse[i], strings[j], size)) break;
+ if(!strncmpiW(&parse[i], strings[j], size)) break;
if(j < 12) {
if(set_month) break;
}
}
- if(retv && i==parse_len && set_year && set_month
- && set_day && (!set_am || hour<13)) {
+ if(i == parse_len && set_year && set_month && set_day && (!set_am || hour<13)) {
if(set_am) {
if(hour == 12) hour = 0;
if(!am) hour += 12;
if(!ad) year = -year+1;
else if(year<100) year += 1900;
- V_VT(retv) = VT_R8;
- V_R8(retv) = time_clip(make_date(make_day(year, month, day),
+ *ret = time_clip(make_date(make_day(year, month, day),
make_time(hour+hour_adjust, min, sec, ms)) + offset*MS_PER_MINUTE);
- if(set_hour_adjust) V_R8(retv) = utc(V_R8(retv), &di);
+ if(set_hour_adjust)
+ *ret = utc(*ret, &di);
+ }else {
+ *ret = NAN;
}
for(i=0; i<sizeof(string_ids)/sizeof(DWORD); i++)
- SysFreeString(strings[i]);
- SysFreeString(parse);
+ heap_free(strings[i]);
+ heap_free(parse);
return S_OK;
}
-static HRESULT DateConstr_parse(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT DateConstr_parse(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- BSTR parse_str;
+ jsstr_t *parse_str;
+ double n;
HRESULT hres;
TRACE("\n");
- if(!arg_cnt(dp)) {
- if(retv)
- num_set_nan(retv);
+ if(!argc) {
+ if(r)
+ *r = jsval_number(NAN);
return S_OK;
}
- hres = to_string(ctx, get_arg(dp,0), ei, &parse_str);
+ hres = to_string(ctx, argv[0], &parse_str);
if(FAILED(hres))
return hres;
- hres = date_parse(parse_str, retv);
+ hres = date_parse(parse_str, &n);
+ jsstr_release(parse_str);
+ if(FAILED(hres))
+ return hres;
- SysFreeString(parse_str);
- return hres;
+ *r = jsval_number(n);
+ return S_OK;
}
-static HRESULT date_utc(script_ctx_t *ctx, DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei)
+static HRESULT date_utc(script_ctx_t *ctx, unsigned argc, jsval_t *argv, double *ret)
{
- VARIANT year, month, vdate, hours, minutes, seconds, ms;
- DOUBLE y;
- int arg_no = arg_cnt(dp);
+ double year, month, vdate, hours, minutes, seconds, ms;
HRESULT hres;
TRACE("\n");
- if(arg_no>0) {
- hres = to_number(ctx, get_arg(dp, 0), ei, &year);
+ if(argc) {
+ hres = to_number(ctx, argv[0], &year);
if(FAILED(hres))
return hres;
- y = num_val(&year);
- if(0<=y && y<=99)
- y += 1900;
+ if(0 <= year && year <= 99)
+ year += 1900;
+ }else {
+ year = 1900;
}
- else y = 1900;
- if(arg_no>1) {
- hres = to_number(ctx, get_arg(dp, 1), ei, &month);
+ if(argc>1) {
+ hres = to_number(ctx, argv[1], &month);
if(FAILED(hres))
return hres;
- }
- else {
- V_VT(&month) = VT_R8;
- V_R8(&month) = 0;
+ }else {
+ month = 0;
}
- if(arg_no>2) {
- hres = to_number(ctx, get_arg(dp, 2), ei, &vdate);
+ if(argc>2) {
+ hres = to_number(ctx, argv[2], &vdate);
if(FAILED(hres))
return hres;
- }
- else {
- V_VT(&vdate) = VT_R8;
- V_R8(&vdate) = 1;
+ }else {
+ vdate = 1;
}
- if(arg_no>3) {
- hres = to_number(ctx, get_arg(dp, 3), ei, &hours);
+ if(argc>3) {
+ hres = to_number(ctx, argv[3], &hours);
if(FAILED(hres))
return hres;
- }
- else {
- V_VT(&hours) = VT_R8;
- V_R8(&hours) = 0;
+ }else {
+ hours = 0;
}
- if(arg_no>4) {
- hres = to_number(ctx, get_arg(dp, 4), ei, &minutes);
+ if(argc>4) {
+ hres = to_number(ctx, argv[4], &minutes);
if(FAILED(hres))
return hres;
- }
- else {
- V_VT(&minutes) = VT_R8;
- V_R8(&minutes) = 0;
+ }else {
+ minutes = 0;
}
- if(arg_no>5) {
- hres = to_number(ctx, get_arg(dp, 5), ei, &seconds);
+ if(argc>5) {
+ hres = to_number(ctx, argv[5], &seconds);
if(FAILED(hres))
return hres;
- }
- else {
- V_VT(&seconds) = VT_R8;
- V_R8(&seconds) = 0;
+ }else {
+ seconds = 0;
}
- if(arg_no>6) {
- hres = to_number(ctx, get_arg(dp, 6), ei, &ms);
+ if(argc>6) {
+ hres = to_number(ctx, argv[6], &ms);
if(FAILED(hres))
return hres;
- }
- else {
- V_VT(&ms) = VT_R8;
- V_R8(&ms) = 0;
- }
-
- if(retv) {
- V_VT(retv) = VT_R8;
- V_R8(retv) = time_clip(make_date(
- make_day(y, num_val(&month), num_val(&vdate)),
- make_time(num_val(&hours), num_val(&minutes),
- num_val(&seconds), num_val(&ms))));
+ } else {
+ ms = 0;
}
+ *ret = time_clip(make_date(make_day(year, month, vdate),
+ make_time(hours, minutes,seconds, ms)));
return S_OK;
}
-static HRESULT DateConstr_UTC(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT DateConstr_UTC(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
+ double n;
+ HRESULT hres;
+
TRACE("\n");
- return date_utc(ctx, dp, retv, ei);
+ hres = date_utc(ctx, argc, argv, &n);
+ if(SUCCEEDED(hres) && r)
+ *r = jsval_number(n);
+ return hres;
}
-static HRESULT DateConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT DateConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- DispatchEx *date;
+ jsdisp_t *date;
HRESULT hres;
TRACE("\n");
switch(flags) {
case DISPATCH_CONSTRUCT:
- switch(arg_cnt(dp)) {
+ switch(argc) {
/* ECMA-262 3rd Edition 15.9.3.3 */
case 0: {
FILETIME time;
/* ECMA-262 3rd Edition 15.9.3.2 */
case 1: {
- VARIANT prim, num;
+ jsval_t prim;
+ double n;
- hres = to_primitive(ctx, get_arg(dp,0), ei, &prim, NO_HINT);
+ hres = to_primitive(ctx, argv[0], &prim, NO_HINT);
if(FAILED(hres))
return hres;
- if(V_VT(&prim) == VT_BSTR)
- hres = date_parse(V_BSTR(&prim), &num);
+ if(is_string(prim))
+ hres = date_parse(get_string(prim), &n);
else
- hres = to_number(ctx, &prim, ei, &num);
+ hres = to_number(ctx, prim, &n);
- VariantClear(&prim);
+ jsval_release(prim);
if(FAILED(hres))
return hres;
- hres = create_date(ctx, NULL, time_clip(num_val(&num)), &date);
+ hres = create_date(ctx, NULL, time_clip(n), &date);
if(FAILED(hres))
return hres;
break;
/* ECMA-262 3rd Edition 15.9.3.1 */
default: {
- VARIANT ret_date;
+ double ret_date;
DateInstance *di;
- hres = date_utc(ctx, dp, &ret_date, ei);
+ hres = date_utc(ctx, argc, argv, &ret_date);
if(FAILED(hres))
return hres;
- hres = create_date(ctx, NULL, num_val(&ret_date), &date);
+ hres = create_date(ctx, NULL, ret_date, &date);
if(FAILED(hres))
return hres;
}
}
- V_VT(retv) = VT_DISPATCH;
- V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(date);
+ *r = jsval_obj(date);
return S_OK;
case INVOKE_FUNC: {
lltime = ((LONGLONG)local_time.dwHighDateTime<<32)
+ local_time.dwLowDateTime;
- return date_to_string(lltime/10000-TIME_EPOCH, FALSE, 0, retv);
+ return date_to_string(lltime/10000-TIME_EPOCH, FALSE, 0, r);
}
default:
NULL
};
-HRESULT create_date_constr(script_ctx_t *ctx, DispatchEx *object_prototype, DispatchEx **ret)
+HRESULT create_date_constr(script_ctx_t *ctx, jsdisp_t *object_prototype, jsdisp_t **ret)
{
- DispatchEx *date;
+ jsdisp_t *date;
HRESULT hres;
static const WCHAR DateW[] = {'D','a','t','e',0};
if(FAILED(hres))
return hres;
- hres = create_builtin_function(ctx, DateConstr_value, DateW, &DateConstr_info,
+ hres = create_builtin_constructor(ctx, DateConstr_value, DateW, &DateConstr_info,
PROPF_CONSTR|7, date, ret);
jsdisp_release(date);
--- /dev/null
+/*
+ * Copyright 2012 Jacek Caban for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "jscript.h"
+
+#include <wine/debug.h>
+
+WINE_DEFAULT_DEBUG_CHANNEL(jscript);
+
+/*
+ * This file implements algorithm for decoding scripts encoded by
+ * screnc.exe. The 'secret' algorithm that's well documented here:
+ * http://www.virtualconspiracy.com/content/articles/breaking-screnc
+ */
+
+static const unsigned char pick_encoding[64] = {
+ 1,2,0,1,2,0,2,0,0,2,0,2,1,0,2,0,
+ 1,0,2,0,1,1,2,0,0,2,1,0,2,0,0,2,
+ 1,1,0,2,0,2,0,1,0,1,1,2,0,1,0,2,
+ 1,0,2,0,1,1,2,0,0,1,1,2,0,1,0,2};
+
+static const unsigned char dictionary[][3] = {
+ {0x00,0x00,0x00}, {0x01,0x01,0x01}, {0x02,0x02,0x02}, {0x03,0x03,0x03},
+ {0x04,0x04,0x04}, {0x05,0x05,0x05}, {0x06,0x06,0x06}, {0x07,0x07,0x07},
+ {0x08,0x08,0x08}, {0x7b,0x57,0x6e}, {0x0a,0x0a,0x0a}, {0x0b,0x0b,0x0b},
+ {0x0c,0x0c,0x0c}, {0x0d,0x0d,0x0d}, {0x0e,0x0e,0x0e}, {0x0f,0x0f,0x0f},
+ {0x10,0x10,0x10}, {0x11,0x11,0x11}, {0x12,0x12,0x12}, {0x13,0x13,0x13},
+ {0x14,0x14,0x14}, {0x15,0x15,0x15}, {0x16,0x16,0x16}, {0x17,0x17,0x17},
+ {0x18,0x18,0x18}, {0x19,0x19,0x19}, {0x1a,0x1a,0x1a}, {0x1b,0x1b,0x1b},
+ {0x1c,0x1c,0x1c}, {0x1d,0x1d,0x1d}, {0x1e,0x1e,0x1e}, {0x1f,0x1f,0x1f},
+ {0x32,0x2e,0x2d}, {0x30,0x47,0x75}, {0x21,0x7a,0x52}, {0x29,0x56,0x60},
+ {0x5b,0x42,0x71}, {0x38,0x6a,0x5e}, {0x33,0x2f,0x49}, {0x3d,0x26,0x5c},
+ {0x58,0x49,0x62}, {0x3a,0x41,0x7d}, {0x35,0x34,0x29}, {0x65,0x32,0x36},
+ {0x39,0x5b,0x20}, {0x5c,0x76,0x7c}, {0x56,0x72,0x7a}, {0x73,0x43,0x7f},
+ {0x66,0x38,0x6b}, {0x4e,0x39,0x63}, {0x45,0x70,0x33}, {0x6b,0x45,0x2b},
+ {0x62,0x68,0x68}, {0x59,0x71,0x51}, {0x78,0x4f,0x66}, {0x5e,0x09,0x76},
+ {0x7d,0x62,0x31}, {0x4a,0x44,0x64}, {0x6d,0x23,0x54}, {0x71,0x75,0x43},
+ {0x00,0x00,0x00}, {0x60,0x7e,0x3a}, {0x00,0x00,0x00}, {0x53,0x5e,0x7e},
+ {0x00,0x00,0x00}, {0x42,0x77,0x45}, {0x27,0x4a,0x2c}, {0x48,0x61,0x2a},
+ {0x72,0x5d,0x74}, {0x75,0x22,0x27}, {0x31,0x4b,0x37}, {0x37,0x6f,0x44},
+ {0x4d,0x4e,0x79}, {0x52,0x3b,0x59}, {0x22,0x4c,0x2f}, {0x54,0x50,0x6f},
+ {0x6a,0x67,0x26}, {0x47,0x2a,0x72}, {0x64,0x7d,0x6a}, {0x2d,0x74,0x39},
+ {0x20,0x54,0x7b}, {0x7f,0x2b,0x3f}, {0x2e,0x2d,0x38}, {0x4c,0x2c,0x77},
+ {0x5d,0x30,0x67}, {0x7e,0x6e,0x53}, {0x6c,0x6b,0x47}, {0x6f,0x66,0x34},
+ {0x79,0x35,0x78}, {0x74,0x25,0x5d}, {0x43,0x21,0x30}, {0x26,0x64,0x23},
+ {0x76,0x4d,0x5a}, {0x25,0x52,0x5b}, {0x24,0x63,0x6c}, {0x2b,0x3f,0x48},
+ {0x28,0x7b,0x55}, {0x23,0x78,0x70}, {0x41,0x29,0x69}, {0x34,0x28,0x2e},
+ {0x09,0x73,0x4c}, {0x2a,0x59,0x21}, {0x44,0x33,0x24}, {0x3f,0x7f,0x4e},
+ {0x77,0x6d,0x50}, {0x3b,0x55,0x09}, {0x55,0x53,0x56}, {0x69,0x7c,0x73},
+ {0x61,0x3a,0x35}, {0x63,0x5f,0x61}, {0x50,0x65,0x4b}, {0x67,0x46,0x58},
+ {0x51,0x58,0x3b}, {0x49,0x31,0x57}, {0x4f,0x69,0x22}, {0x46,0x6c,0x6d},
+ {0x68,0x5a,0x4d}, {0x7c,0x48,0x25}, {0x36,0x27,0x28}, {0x70,0x5c,0x46},
+ {0x6e,0x3d,0x4a}, {0x7a,0x24,0x32}, {0x2f,0x79,0x41}, {0x5f,0x37,0x3d},
+ {0x4b,0x60,0x5f}, {0x5a,0x51,0x4f}, {0x2c,0x20,0x42}, {0x57,0x36,0x65}};
+
+static const int digits[] = {
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
+ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
+ 0x3c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
+ 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
+ 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
+ 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
+ 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
+ 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
+ 0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff};
+
+static BOOL decode_dword(const WCHAR *p, DWORD *ret)
+{
+ DWORD i;
+
+ for(i=0; i<6; i++) {
+ if(p[i] > sizeof(digits)/sizeof(*digits) || digits[p[i]] == 0xff)
+ return FALSE;
+ }
+ if(p[6] != '=' || p[7] != '=')
+ return FALSE;
+
+ *ret = (digits[p[0]] << 2)
+ + (digits[p[1]] >> 4)
+ + ((digits[p[1]] & 0xf) << 12)
+ + ((digits[p[2]] >> 2) << 8)
+ + ((digits[p[2]] & 0x3) << 22)
+ + (digits[p[3]] << 16)
+ + ((digits[p[4]] << 2) << 24)
+ + ((digits[p[5]] >> 4) << 24);
+ return TRUE;
+}
+
+HRESULT decode_source(WCHAR *code)
+{
+ const WCHAR *src = code;
+ WCHAR *dst = code;
+
+ static const WCHAR decode_beginW[] = {'#','@','~','^'};
+ static const WCHAR decode_endW[] = {'^','#','~','@'};
+
+ while(*src) {
+ if(!strncmpW(src, decode_beginW, sizeof(decode_beginW)/sizeof(*decode_beginW))) {
+ DWORD len, i, j=0, csum, s=0;
+
+ src += sizeof(decode_beginW)/sizeof(*decode_beginW);
+
+ if(!decode_dword(src, &len))
+ return JS_E_INVALID_CHAR;
+
+ src += 8;
+
+ for(i=0; i<len; i++) {
+ if (src[i] == '@') {
+ switch(src[++i]) {
+ case '#':
+ s += dst[j++] = '\r';
+ break;
+ case '&':
+ s += dst[j++] = '\n';
+ break;
+ case '!':
+ s += dst[j++] = '<';
+ break;
+ case '*':
+ s += dst[j++] = '>';
+ break;
+ case '$':
+ s += dst[j++] = '@';
+ break;
+ default:
+ FIXME("unescape %c\n", src[i]);
+ return E_FAIL;
+ }
+ }else if (src[i] < 128) {
+ s += dst[j] = dictionary[src[i]][pick_encoding[j%64]];
+ j++;
+ }else {
+ FIXME("Unsupported char %c\n", src[i]);
+ return E_FAIL;
+ }
+ }
+
+ src += len;
+ dst += j;
+
+ if(!decode_dword(src, &csum) || s != csum)
+ return JS_E_INVALID_CHAR;
+ src += 8;
+
+ if(strncmpW(src, decode_endW, sizeof(decode_endW)/sizeof(*decode_endW)))
+ return JS_E_INVALID_CHAR;
+ src += sizeof(decode_endW)/sizeof(*decode_endW);
+ }else {
+ *dst++ = *src++;
+ }
+ }
+
+ *dst = 0;
+
+ TRACE("decoded %s\n", debugstr_w(code));
+ return S_OK;
+}
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
+#include <assert.h>
+
#include "jscript.h"
//#include "wine/unicode.h"
WINE_DEFAULT_DEBUG_CHANNEL(jscript);
/*
- * This IID is used to get DispatchEx objecto from interface.
- * We might consider using private insteface instead.
+ * This IID is used to get jsdisp_t objecto from interface.
+ * We might consider using private interface instead.
*/
static const IID IID_IDispatchJS =
{0x719c3050,0xf9d3,0x11cf,{0xa4,0x93,0x00,0x40,0x05,0x23,0xa8,0xa6}};
#define FDEX_VERSION_MASK 0xf0000000
+#define GOLDEN_RATIO 0x9E3779B9U
typedef enum {
- PROP_VARIANT,
+ PROP_JSVAL,
PROP_BUILTIN,
PROP_PROTREF,
- PROP_DELETED
+ PROP_DELETED,
+ PROP_IDX
} prop_type_t;
struct _dispex_prop_t {
WCHAR *name;
+ unsigned hash;
prop_type_t type;
DWORD flags;
union {
- VARIANT var;
+ jsval_t val;
const builtin_prop_t *p;
DWORD ref;
+ unsigned idx;
} u;
+
+ int bucket_head;
+ int bucket_next;
};
-static inline DISPID prop_to_id(DispatchEx *This, dispex_prop_t *prop)
+static inline DISPID prop_to_id(jsdisp_t *This, dispex_prop_t *prop)
{
return prop - This->props;
}
-static inline dispex_prop_t *get_prop(DispatchEx *This, DISPID id)
+static inline dispex_prop_t *get_prop(jsdisp_t *This, DISPID id)
{
if(id < 0 || id >= This->prop_cnt || This->props[id].type == PROP_DELETED)
return NULL;
return This->props+id;
}
-static DWORD get_flags(DispatchEx *This, dispex_prop_t *prop)
+static DWORD get_flags(jsdisp_t *This, dispex_prop_t *prop)
{
if(prop->type == PROP_PROTREF) {
dispex_prop_t *parent = get_prop(This->prototype, prop->u.ref);
return prop->flags;
}
-static const builtin_prop_t *find_builtin_prop(DispatchEx *This, const WCHAR *name)
+static const builtin_prop_t *find_builtin_prop(jsdisp_t *This, const WCHAR *name)
{
int min = 0, max, i, r;
return NULL;
}
-static dispex_prop_t *alloc_prop(DispatchEx *This, const WCHAR *name, prop_type_t type, DWORD flags)
+static inline unsigned string_hash(const WCHAR *name)
{
- dispex_prop_t *ret;
+ unsigned h = 0;
+ for(; *name; name++)
+ h = (h>>(sizeof(unsigned)*8-4)) ^ (h<<4) ^ tolowerW(*name);
+ return h;
+}
- if(This->buf_size == This->prop_cnt) {
- dispex_prop_t *tmp = heap_realloc(This->props, (This->buf_size<<=1)*sizeof(*This->props));
- if(!tmp)
- return NULL;
- This->props = tmp;
+static inline unsigned get_props_idx(jsdisp_t *This, unsigned hash)
+{
+ return (hash*GOLDEN_RATIO) & (This->buf_size-1);
+}
+
+static inline HRESULT resize_props(jsdisp_t *This)
+{
+ dispex_prop_t *props;
+ int i, bucket;
+
+ if(This->buf_size != This->prop_cnt)
+ return S_FALSE;
+
+ props = heap_realloc(This->props, sizeof(dispex_prop_t)*This->buf_size*2);
+ if(!props)
+ return E_OUTOFMEMORY;
+ This->buf_size *= 2;
+ This->props = props;
+
+ for(i=0; i<This->buf_size; i++) {
+ This->props[i].bucket_head = 0;
+ This->props[i].bucket_next = 0;
}
- ret = This->props + This->prop_cnt++;
- ret->type = type;
- ret->flags = flags;
- ret->name = heap_strdupW(name);
- if(!ret->name)
+ for(i=1; i<This->prop_cnt; i++) {
+ props = This->props+i;
+
+ bucket = get_props_idx(This, props->hash);
+ props->bucket_next = This->props[bucket].bucket_head;
+ This->props[bucket].bucket_head = i;
+ }
+
+ return S_OK;
+}
+
+static inline dispex_prop_t* alloc_prop(jsdisp_t *This, const WCHAR *name, prop_type_t type, DWORD flags)
+{
+ dispex_prop_t *prop;
+ unsigned bucket;
+
+ if(FAILED(resize_props(This)))
return NULL;
- return ret;
+ prop = &This->props[This->prop_cnt];
+ prop->name = heap_strdupW(name);
+ if(!prop->name)
+ return NULL;
+ prop->type = type;
+ prop->flags = flags;
+ prop->hash = string_hash(name);
+
+ bucket = get_props_idx(This, prop->hash);
+ prop->bucket_next = This->props[bucket].bucket_head;
+ This->props[bucket].bucket_head = This->prop_cnt++;
+ return prop;
}
-static dispex_prop_t *alloc_protref(DispatchEx *This, const WCHAR *name, DWORD ref)
+static dispex_prop_t *alloc_protref(jsdisp_t *This, const WCHAR *name, DWORD ref)
{
dispex_prop_t *ret;
return ret;
}
-static HRESULT find_prop_name(DispatchEx *This, const WCHAR *name, dispex_prop_t **ret)
+static HRESULT find_prop_name(jsdisp_t *This, unsigned hash, const WCHAR *name, dispex_prop_t **ret)
{
const builtin_prop_t *builtin;
+ unsigned bucket, pos, prev = 0;
dispex_prop_t *prop;
- for(prop = This->props; prop < This->props+This->prop_cnt; prop++) {
- if(prop->name && !strcmpW(prop->name, name)) {
- *ret = prop;
+ bucket = get_props_idx(This, hash);
+ pos = This->props[bucket].bucket_head;
+ while(pos != 0) {
+ if(!strcmpW(name, This->props[pos].name)) {
+ if(prev != 0) {
+ This->props[prev].bucket_next = This->props[pos].bucket_next;
+ This->props[pos].bucket_next = This->props[bucket].bucket_head;
+ This->props[bucket].bucket_head = pos;
+ }
+
+ *ret = &This->props[pos];
return S_OK;
}
+
+ prev = pos;
+ pos = This->props[pos].bucket_next;
}
builtin = find_builtin_prop(This, name);
return S_OK;
}
+ if(This->builtin_info->idx_length) {
+ const WCHAR *ptr;
+ unsigned idx = 0;
+
+ for(ptr = name; isdigitW(*ptr) && idx < 0x10000; ptr++)
+ idx = idx*10 + (*ptr-'0');
+ if(!*ptr && idx < This->builtin_info->idx_length(This)) {
+ prop = alloc_prop(This, name, PROP_IDX, This->builtin_info->idx_put ? 0 : PROPF_CONST);
+ if(!prop)
+ return E_OUTOFMEMORY;
+
+ prop->u.idx = idx;
+ *ret = prop;
+ return S_OK;
+ }
+ }
+
*ret = NULL;
return S_OK;
}
-static HRESULT find_prop_name_prot(DispatchEx *This, const WCHAR *name, dispex_prop_t **ret)
+static HRESULT find_prop_name_prot(jsdisp_t *This, unsigned hash, const WCHAR *name, dispex_prop_t **ret)
{
- dispex_prop_t *prop;
+ dispex_prop_t *prop, *del=NULL;
HRESULT hres;
- hres = find_prop_name(This, name, &prop);
+ hres = find_prop_name(This, hash, name, &prop);
if(FAILED(hres))
return hres;
- if(prop) {
+ if(prop && prop->type==PROP_DELETED) {
+ del = prop;
+ } else if(prop) {
*ret = prop;
return S_OK;
}
if(This->prototype) {
- hres = find_prop_name_prot(This->prototype, name, &prop);
+ hres = find_prop_name_prot(This->prototype, hash, name, &prop);
if(FAILED(hres))
return hres;
if(prop) {
- prop = alloc_protref(This, prop->name, prop - This->prototype->props);
- if(!prop)
- return E_OUTOFMEMORY;
+ if(del) {
+ del->type = PROP_PROTREF;
+ del->flags = 0;
+ del->u.ref = prop - This->prototype->props;
+ prop = del;
+ }else {
+ prop = alloc_protref(This, prop->name, prop - This->prototype->props);
+ if(!prop)
+ return E_OUTOFMEMORY;
+ }
+
*ret = prop;
return S_OK;
}
}
- *ret = prop;
+ *ret = del;
return S_OK;
}
-static HRESULT ensure_prop_name(DispatchEx *This, const WCHAR *name, BOOL search_prot, DWORD create_flags, dispex_prop_t **ret)
+static HRESULT ensure_prop_name(jsdisp_t *This, const WCHAR *name, BOOL search_prot, DWORD create_flags, dispex_prop_t **ret)
{
dispex_prop_t *prop;
HRESULT hres;
if(search_prot)
- hres = find_prop_name_prot(This, name, &prop);
+ hres = find_prop_name_prot(This, string_hash(name), name, &prop);
else
- hres = find_prop_name(This, name, &prop);
- if(SUCCEEDED(hres) && !prop) {
- TRACE("creating prop %s\n", debugstr_w(name));
+ hres = find_prop_name(This, string_hash(name), name, &prop);
+ if(SUCCEEDED(hres) && (!prop || prop->type == PROP_DELETED)) {
+ TRACE("creating prop %s flags %x\n", debugstr_w(name), create_flags);
- prop = alloc_prop(This, name, PROP_VARIANT, create_flags);
- if(!prop)
- return E_OUTOFMEMORY;
- VariantInit(&prop->u.var);
+ if(prop) {
+ prop->type = PROP_JSVAL;
+ prop->flags = create_flags;
+ prop->u.val = jsval_undefined();
+ }else {
+ prop = alloc_prop(This, name, PROP_JSVAL, create_flags);
+ if(!prop)
+ return E_OUTOFMEMORY;
+ }
+
+ prop->u.val = jsval_undefined();
}
*ret = prop;
return hres;
}
-static HRESULT set_this(DISPPARAMS *dp, DISPPARAMS *olddp, IDispatch *jsthis)
+static IDispatch *get_this(DISPPARAMS *dp)
{
- VARIANTARG *oldargs;
- int i;
+ DWORD i;
- static DISPID this_id = DISPID_THIS;
+ for(i=0; i < dp->cNamedArgs; i++) {
+ if(dp->rgdispidNamedArgs[i] == DISPID_THIS) {
+ if(V_VT(dp->rgvarg+i) == VT_DISPATCH)
+ return V_DISPATCH(dp->rgvarg+i);
- *dp = *olddp;
-
- for(i = 0; i < dp->cNamedArgs; i++) {
- if(dp->rgdispidNamedArgs[i] == DISPID_THIS)
- return S_OK;
+ WARN("This is not VT_DISPATCH\n");
+ return NULL;
+ }
}
- oldargs = dp->rgvarg;
- dp->rgvarg = heap_alloc((dp->cArgs+1) * sizeof(VARIANTARG));
- if(!dp->rgvarg)
- return E_OUTOFMEMORY;
- memcpy(dp->rgvarg+1, oldargs, dp->cArgs*sizeof(VARIANTARG));
- V_VT(dp->rgvarg) = VT_DISPATCH;
- V_DISPATCH(dp->rgvarg) = jsthis;
- dp->cArgs++;
-
- if(dp->cNamedArgs) {
- DISPID *old = dp->rgdispidNamedArgs;
- dp->rgdispidNamedArgs = heap_alloc((dp->cNamedArgs+1)*sizeof(DISPID));
- if(!dp->rgdispidNamedArgs) {
- heap_free(dp->rgvarg);
- return E_OUTOFMEMORY;
- }
+ TRACE("no this passed\n");
+ return NULL;
+}
- memcpy(dp->rgdispidNamedArgs+1, old, dp->cNamedArgs*sizeof(DISPID));
- dp->rgdispidNamedArgs[0] = DISPID_THIS;
- dp->cNamedArgs++;
+static HRESULT convert_params(const DISPPARAMS *dp, jsval_t *buf, unsigned *argc, jsval_t **ret)
+{
+ jsval_t *argv;
+ unsigned cnt;
+ unsigned i;
+ HRESULT hres;
+
+ cnt = dp->cArgs - dp->cNamedArgs;
+
+ if(cnt > 6) {
+ argv = heap_alloc(cnt * sizeof(*argv));
+ if(!argv)
+ return E_OUTOFMEMORY;
}else {
- dp->rgdispidNamedArgs = &this_id;
- dp->cNamedArgs = 1;
+ argv = buf;
}
+ for(i = 0; i < cnt; i++) {
+ hres = variant_to_jsval(dp->rgvarg+dp->cArgs-i-1, argv+i);
+ if(FAILED(hres)) {
+ while(i--)
+ jsval_release(argv[i]);
+ if(argv != buf)
+ heap_free(argv);
+ return hres;
+ }
+ }
+
+ *argc = cnt;
+ *ret = argv;
return S_OK;
}
-static HRESULT invoke_prop_func(DispatchEx *This, DispatchEx *jsthis, dispex_prop_t *prop, WORD flags,
- DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT invoke_prop_func(jsdisp_t *This, IDispatch *jsthis, dispex_prop_t *prop, WORD flags,
+ unsigned argc, jsval_t *argv, jsval_t *r, IServiceProvider *caller)
{
HRESULT hres;
switch(prop->type) {
case PROP_BUILTIN: {
- vdisp_t vthis;
-
- if(flags == DISPATCH_CONSTRUCT && (prop->flags & DISPATCH_METHOD)) {
+ if(flags == DISPATCH_CONSTRUCT && (prop->flags & PROPF_METHOD)) {
WARN("%s is not a constructor\n", debugstr_w(prop->name));
return E_INVALIDARG;
}
- set_jsdisp(&vthis, jsthis);
- hres = prop->u.p->invoke(This->ctx, &vthis, flags, dp, retv, ei, caller);
- vdisp_release(&vthis);
+ if(prop->name || This->builtin_info->class != JSCLASS_FUNCTION) {
+ vdisp_t vthis;
+
+ if(jsthis)
+ set_disp(&vthis, jsthis);
+ else
+ set_jsdisp(&vthis, This);
+ hres = prop->u.p->invoke(This->ctx, &vthis, flags, argc, argv, r);
+ vdisp_release(&vthis);
+ }else {
+ /* Function object calls are special case */
+ hres = Function_invoke(This, jsthis, flags, argc, argv, r);
+ }
return hres;
}
case PROP_PROTREF:
- return invoke_prop_func(This->prototype, jsthis, This->prototype->props+prop->u.ref, flags, dp, retv, ei, caller);
- case PROP_VARIANT: {
- DISPPARAMS new_dp;
-
- if(V_VT(&prop->u.var) != VT_DISPATCH) {
- FIXME("invoke vt %d\n", V_VT(&prop->u.var));
+ return invoke_prop_func(This->prototype, jsthis, This->prototype->props+prop->u.ref,
+ flags, argc, argv, r, caller);
+ case PROP_JSVAL: {
+ if(!is_object_instance(prop->u.val)) {
+ FIXME("invoke %s\n", debugstr_jsval(prop->u.val));
return E_FAIL;
}
- TRACE("call %s %p\n", debugstr_w(prop->name), V_DISPATCH(&prop->u.var));
+ TRACE("call %s %p\n", debugstr_w(prop->name), get_object(prop->u.val));
- hres = set_this(&new_dp, dp, (IDispatch*)_IDispatchEx_(jsthis));
- if(FAILED(hres))
- return hres;
-
- hres = disp_call(This->ctx, V_DISPATCH(&prop->u.var), DISPID_VALUE, flags, &new_dp, retv, ei, caller);
-
- if(new_dp.rgvarg != dp->rgvarg) {
- heap_free(new_dp.rgvarg);
- if(new_dp.cNamedArgs > 1)
- heap_free(new_dp.rgdispidNamedArgs);
- }
-
- return hres;
+ return disp_call_value(This->ctx, get_object(prop->u.val), jsthis, flags, argc, argv, r);
}
- default:
- ERR("type %d\n", prop->type);
+ case PROP_IDX:
+ FIXME("Invoking PROP_IDX not yet supported\n");
+ return E_NOTIMPL;
+ case PROP_DELETED:
+ assert(0);
}
+ assert(0);
return E_FAIL;
}
-static HRESULT prop_get(DispatchEx *This, dispex_prop_t *prop, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT prop_get(jsdisp_t *This, dispex_prop_t *prop, DISPPARAMS *dp,
+ jsval_t *r, IServiceProvider *caller)
{
HRESULT hres;
switch(prop->type) {
case PROP_BUILTIN:
if(prop->u.p->flags & PROPF_METHOD) {
- DispatchEx *obj;
+ jsdisp_t *obj;
hres = create_builtin_function(This->ctx, prop->u.p->invoke, prop->u.p->name, NULL,
prop->u.p->flags, NULL, &obj);
if(FAILED(hres))
break;
- prop->type = PROP_VARIANT;
- V_VT(&prop->u.var) = VT_DISPATCH;
- V_DISPATCH(&prop->u.var) = (IDispatch*)_IDispatchEx_(obj);
+ prop->type = PROP_JSVAL;
+ prop->u.val = jsval_obj(obj);
- hres = VariantCopy(retv, &prop->u.var);
+ jsdisp_addref(obj);
+ *r = jsval_obj(obj);
}else {
vdisp_t vthis;
set_jsdisp(&vthis, This);
- hres = prop->u.p->invoke(This->ctx, &vthis, DISPATCH_PROPERTYGET, dp, retv, ei, caller);
+ hres = prop->u.p->invoke(This->ctx, &vthis, DISPATCH_PROPERTYGET, 0, NULL, r);
vdisp_release(&vthis);
}
break;
case PROP_PROTREF:
- hres = prop_get(This->prototype, This->prototype->props+prop->u.ref, dp, retv, ei, caller);
+ hres = prop_get(This->prototype, This->prototype->props+prop->u.ref, dp, r, caller);
+ break;
+ case PROP_JSVAL:
+ hres = jsval_copy(prop->u.val, r);
break;
- case PROP_VARIANT:
- hres = VariantCopy(retv, &prop->u.var);
+ case PROP_IDX:
+ hres = This->builtin_info->idx_get(This, prop->u.idx, r);
break;
default:
ERR("type %d\n", prop->type);
return hres;
}
- TRACE("%s ret %s\n", debugstr_w(prop->name), debugstr_variant(retv));
+ TRACE("%s ret %s\n", debugstr_w(prop->name), debugstr_jsval(*r));
return hres;
}
-static HRESULT prop_put(DispatchEx *This, dispex_prop_t *prop, VARIANT *val,
- jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT prop_put(jsdisp_t *This, dispex_prop_t *prop, jsval_t val, IServiceProvider *caller)
{
HRESULT hres;
switch(prop->type) {
case PROP_BUILTIN:
if(!(prop->flags & PROPF_METHOD)) {
- DISPPARAMS dp = {val, NULL, 1, 0};
vdisp_t vthis;
set_jsdisp(&vthis, This);
- hres = prop->u.p->invoke(This->ctx, &vthis, DISPATCH_PROPERTYPUT, &dp, NULL, ei, caller);
+ hres = prop->u.p->invoke(This->ctx, &vthis, DISPATCH_PROPERTYPUT, 1, &val, NULL);
vdisp_release(&vthis);
return hres;
}
+ /* fall through */
case PROP_PROTREF:
- prop->type = PROP_VARIANT;
+ prop->type = PROP_JSVAL;
prop->flags = PROPF_ENUM;
- V_VT(&prop->u.var) = VT_EMPTY;
+ prop->u.val = jsval_undefined();
break;
- case PROP_VARIANT:
- VariantClear(&prop->u.var);
+ case PROP_JSVAL:
+ jsval_release(prop->u.val);
break;
+ case PROP_IDX:
+ return This->builtin_info->idx_put(This, prop->u.idx, val);
default:
ERR("type %d\n", prop->type);
return E_FAIL;
}
- hres = VariantCopy(&prop->u.var, val);
- if(FAILED(hres))
+ TRACE("%s = %s\n", debugstr_w(prop->name), debugstr_jsval(val));
+
+ hres = jsval_copy(val, &prop->u.val);
+ if(FAILED(hres)) {
+ prop->u.val = jsval_undefined();
return hres;
+ }
if(This->builtin_info->on_put)
This->builtin_info->on_put(This, prop->name);
- TRACE("%s = %s\n", debugstr_w(prop->name), debugstr_variant(val));
return S_OK;
}
-static HRESULT fill_protrefs(DispatchEx *This)
+static HRESULT fill_protrefs(jsdisp_t *This)
{
dispex_prop_t *iter, *prop;
HRESULT hres;
for(iter = This->prototype->props; iter < This->prototype->props+This->prototype->prop_cnt; iter++) {
if(!iter->name)
continue;
- hres = find_prop_name(This, iter->name, &prop);
+ hres = find_prop_name(This, iter->hash, iter->name, &prop);
if(FAILED(hres))
return hres;
- if(!prop) {
- prop = alloc_protref(This, iter->name, iter - This->prototype->props);
- if(!prop)
- return E_OUTOFMEMORY;
+ if(!prop || prop->type==PROP_DELETED) {
+ if(prop) {
+ prop->type = PROP_PROTREF;
+ prop->flags = 0;
+ prop->u.ref = iter - This->prototype->props;
+ }else {
+ prop = alloc_protref(This, iter->name, iter - This->prototype->props);
+ if(!prop)
+ return E_OUTOFMEMORY;
+ }
}
}
return S_OK;
}
-#define DISPATCHEX_THIS(iface) DEFINE_THIS(DispatchEx, IDispatchEx, iface)
+static inline jsdisp_t *impl_from_IDispatchEx(IDispatchEx *iface)
+{
+ return CONTAINING_RECORD(iface, jsdisp_t, IDispatchEx_iface);
+}
static HRESULT WINAPI DispatchEx_QueryInterface(IDispatchEx *iface, REFIID riid, void **ppv)
{
- DispatchEx *This = DISPATCHEX_THIS(iface);
+ jsdisp_t *This = impl_from_IDispatchEx(iface);
if(IsEqualGUID(&IID_IUnknown, riid)) {
TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
- *ppv = _IDispatchEx_(This);
+ *ppv = &This->IDispatchEx_iface;
}else if(IsEqualGUID(&IID_IDispatch, riid)) {
TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
- *ppv = _IDispatchEx_(This);
+ *ppv = &This->IDispatchEx_iface;
}else if(IsEqualGUID(&IID_IDispatchEx, riid)) {
TRACE("(%p)->(IID_IDispatchEx %p)\n", This, ppv);
- *ppv = _IDispatchEx_(This);
+ *ppv = &This->IDispatchEx_iface;
}else if(IsEqualGUID(&IID_IDispatchJS, riid)) {
TRACE("(%p)->(IID_IDispatchJS %p)\n", This, ppv);
- IUnknown_AddRef(_IDispatchEx_(This));
+ jsdisp_addref(This);
*ppv = This;
return S_OK;
}else {
return E_NOINTERFACE;
}
- IUnknown_AddRef((IUnknown*)*ppv);
+ jsdisp_addref(This);
return S_OK;
}
static ULONG WINAPI DispatchEx_AddRef(IDispatchEx *iface)
{
- DispatchEx *This = DISPATCHEX_THIS(iface);
- LONG ref = InterlockedIncrement(&This->ref);
-
- TRACE("(%p) ref=%d\n", This, ref);
-
- return ref;
+ jsdisp_t *This = impl_from_IDispatchEx(iface);
+ jsdisp_addref(This);
+ return This->ref;
}
static ULONG WINAPI DispatchEx_Release(IDispatchEx *iface)
{
- DispatchEx *This = DISPATCHEX_THIS(iface);
- LONG ref = InterlockedDecrement(&This->ref);
-
- TRACE("(%p) ref=%d\n", This, ref);
-
- if(!ref) {
- dispex_prop_t *prop;
-
- for(prop = This->props; prop < This->props+This->prop_cnt; prop++) {
- if(prop->type == PROP_VARIANT)
- VariantClear(&prop->u.var);
- heap_free(prop->name);
- }
- heap_free(This->props);
- script_release(This->ctx);
- if(This->prototype)
- jsdisp_release(This->prototype);
-
- if(This->builtin_info->destructor)
- This->builtin_info->destructor(This);
- else
- heap_free(This);
- }
-
+ jsdisp_t *This = impl_from_IDispatchEx(iface);
+ ULONG ref = --This->ref;
+ if(!ref)
+ jsdisp_free(This);
return ref;
}
static HRESULT WINAPI DispatchEx_GetTypeInfoCount(IDispatchEx *iface, UINT *pctinfo)
{
- DispatchEx *This = DISPATCHEX_THIS(iface);
+ jsdisp_t *This = impl_from_IDispatchEx(iface);
TRACE("(%p)->(%p)\n", This, pctinfo);
static HRESULT WINAPI DispatchEx_GetTypeInfo(IDispatchEx *iface, UINT iTInfo, LCID lcid,
ITypeInfo **ppTInfo)
{
- DispatchEx *This = DISPATCHEX_THIS(iface);
+ jsdisp_t *This = impl_from_IDispatchEx(iface);
FIXME("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
return E_NOTIMPL;
}
LPOLESTR *rgszNames, UINT cNames, LCID lcid,
DISPID *rgDispId)
{
- DispatchEx *This = DISPATCHEX_THIS(iface);
+ jsdisp_t *This = impl_from_IDispatchEx(iface);
UINT i;
HRESULT hres;
lcid, rgDispId);
for(i=0; i < cNames; i++) {
- hres = IDispatchEx_GetDispID(_IDispatchEx_(This), rgszNames[i], 0, rgDispId+i);
+ hres = IDispatchEx_GetDispID(&This->IDispatchEx_iface, rgszNames[i], 0, rgDispId+i);
if(FAILED(hres))
return hres;
}
REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
{
- DispatchEx *This = DISPATCHEX_THIS(iface);
+ jsdisp_t *This = impl_from_IDispatchEx(iface);
TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
- return IDispatchEx_InvokeEx(_IDispatchEx_(This), dispIdMember, lcid, wFlags,
+ return IDispatchEx_InvokeEx(&This->IDispatchEx_iface, dispIdMember, lcid, wFlags,
pDispParams, pVarResult, pExcepInfo, NULL);
}
static HRESULT WINAPI DispatchEx_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD grfdex, DISPID *pid)
{
- DispatchEx *This = DISPATCHEX_THIS(iface);
+ jsdisp_t *This = impl_from_IDispatchEx(iface);
TRACE("(%p)->(%s %x %p)\n", This, debugstr_w(bstrName), grfdex, pid);
static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller)
{
- DispatchEx *This = DISPATCHEX_THIS(iface);
+ jsdisp_t *This = impl_from_IDispatchEx(iface);
dispex_prop_t *prop;
- jsexcept_t jsexcept;
HRESULT hres;
TRACE("(%p)->(%x %x %x %p %p %p %p)\n", This, id, lcid, wFlags, pdp, pvarRes, pei, pspCaller);
return DISP_E_MEMBERNOTFOUND;
}
- memset(&jsexcept, 0, sizeof(jsexcept));
+ clear_ei(This->ctx);
switch(wFlags) {
+ case DISPATCH_METHOD|DISPATCH_PROPERTYGET:
+ wFlags = DISPATCH_METHOD;
+ /* fall through */
case DISPATCH_METHOD:
- case DISPATCH_CONSTRUCT:
- hres = invoke_prop_func(This, This, prop, wFlags, pdp, pvarRes, &jsexcept, pspCaller);
+ case DISPATCH_CONSTRUCT: {
+ jsval_t *argv, buf[6], r;
+ unsigned argc;
+
+ hres = convert_params(pdp, buf, &argc, &argv);
+ if(FAILED(hres))
+ return hres;
+
+ hres = invoke_prop_func(This, get_this(pdp), prop, wFlags, argc, argv, pvarRes ? &r : NULL, pspCaller);
+ if(argv != buf)
+ heap_free(argv);
+ if(SUCCEEDED(hres) && pvarRes) {
+ hres = jsval_to_variant(r, pvarRes);
+ jsval_release(r);
+ }
break;
- case DISPATCH_PROPERTYGET:
- hres = prop_get(This, prop, pdp, pvarRes, &jsexcept, pspCaller);
+ }
+ case DISPATCH_PROPERTYGET: {
+ jsval_t r;
+
+ hres = prop_get(This, prop, pdp, &r, pspCaller);
+ if(SUCCEEDED(hres)) {
+ hres = jsval_to_variant(r, pvarRes);
+ jsval_release(r);
+ }
break;
+ }
case DISPATCH_PROPERTYPUT: {
+ jsval_t val;
DWORD i;
for(i=0; i < pdp->cNamedArgs; i++) {
return DISP_E_PARAMNOTOPTIONAL;
}
- hres = prop_put(This, prop, pdp->rgvarg+i, &jsexcept, pspCaller);
+ hres = variant_to_jsval(pdp->rgvarg+i, &val);
+ if(FAILED(hres))
+ return hres;
+
+ hres = prop_put(This, prop, val, pspCaller);
+ jsval_release(val);
break;
}
default:
}
if(pei)
- *pei = jsexcept.ei;
-
+ *pei = This->ctx->ei.ei;
return hres;
}
-static HRESULT delete_prop(dispex_prop_t *prop)
+static HRESULT delete_prop(dispex_prop_t *prop, BOOL *ret)
{
- heap_free(prop->name);
- prop->name = NULL;
- prop->type = PROP_DELETED;
+ if(prop->flags & PROPF_DONTDELETE) {
+ *ret = FALSE;
+ return S_OK;
+ }
+ *ret = TRUE; /* FIXME: not exactly right */
+
+ if(prop->type == PROP_JSVAL) {
+ jsval_release(prop->u.val);
+ prop->type = PROP_DELETED;
+ }
return S_OK;
}
static HRESULT WINAPI DispatchEx_DeleteMemberByName(IDispatchEx *iface, BSTR bstrName, DWORD grfdex)
{
- DispatchEx *This = DISPATCHEX_THIS(iface);
+ jsdisp_t *This = impl_from_IDispatchEx(iface);
dispex_prop_t *prop;
+ BOOL b;
HRESULT hres;
TRACE("(%p)->(%s %x)\n", This, debugstr_w(bstrName), grfdex);
if(grfdex & ~(fdexNameCaseSensitive|fdexNameEnsure|fdexNameImplicit|FDEX_VERSION_MASK))
FIXME("Unsupported grfdex %x\n", grfdex);
- hres = find_prop_name(This, bstrName, &prop);
+ hres = find_prop_name(This, string_hash(bstrName), bstrName, &prop);
if(FAILED(hres))
return hres;
if(!prop) {
return S_OK;
}
- return delete_prop(prop);
+ return delete_prop(prop, &b);
}
static HRESULT WINAPI DispatchEx_DeleteMemberByDispID(IDispatchEx *iface, DISPID id)
{
- DispatchEx *This = DISPATCHEX_THIS(iface);
+ jsdisp_t *This = impl_from_IDispatchEx(iface);
dispex_prop_t *prop;
+ BOOL b;
TRACE("(%p)->(%x)\n", This, id);
return DISP_E_MEMBERNOTFOUND;
}
- return delete_prop(prop);
+ return delete_prop(prop, &b);
}
static HRESULT WINAPI DispatchEx_GetMemberProperties(IDispatchEx *iface, DISPID id, DWORD grfdexFetch, DWORD *pgrfdex)
{
- DispatchEx *This = DISPATCHEX_THIS(iface);
+ jsdisp_t *This = impl_from_IDispatchEx(iface);
FIXME("(%p)->(%x %x %p)\n", This, id, grfdexFetch, pgrfdex);
return E_NOTIMPL;
}
static HRESULT WINAPI DispatchEx_GetMemberName(IDispatchEx *iface, DISPID id, BSTR *pbstrName)
{
- DispatchEx *This = DISPATCHEX_THIS(iface);
+ jsdisp_t *This = impl_from_IDispatchEx(iface);
dispex_prop_t *prop;
TRACE("(%p)->(%x %p)\n", This, id, pbstrName);
static HRESULT WINAPI DispatchEx_GetNextDispID(IDispatchEx *iface, DWORD grfdex, DISPID id, DISPID *pid)
{
- DispatchEx *This = DISPATCHEX_THIS(iface);
+ jsdisp_t *This = impl_from_IDispatchEx(iface);
dispex_prop_t *iter;
HRESULT hres;
return hres;
}
- iter = get_prop(This, id+1);
- if(!iter) {
+ if(id+1>=0 && id+1<This->prop_cnt) {
+ iter = &This->props[id+1];
+ }else {
*pid = DISPID_STARTENUM;
return S_FALSE;
}
while(iter < This->props + This->prop_cnt) {
- if(iter->name && (get_flags(This, iter) & PROPF_ENUM)) {
+ if(iter->name && (get_flags(This, iter) & PROPF_ENUM) && iter->type!=PROP_DELETED) {
*pid = prop_to_id(This, iter);
return S_OK;
}
static HRESULT WINAPI DispatchEx_GetNameSpaceParent(IDispatchEx *iface, IUnknown **ppunk)
{
- DispatchEx *This = DISPATCHEX_THIS(iface);
+ jsdisp_t *This = impl_from_IDispatchEx(iface);
FIXME("(%p)->(%p)\n", This, ppunk);
return E_NOTIMPL;
}
-#undef DISPATCHEX_THIS
-
static IDispatchExVtbl DispatchExVtbl = {
DispatchEx_QueryInterface,
DispatchEx_AddRef,
DispatchEx_GetNameSpaceParent
};
-HRESULT init_dispex(DispatchEx *dispex, script_ctx_t *ctx, const builtin_info_t *builtin_info, DispatchEx *prototype)
+jsdisp_t *as_jsdisp(IDispatch *disp)
+{
+ assert(disp->lpVtbl == (IDispatchVtbl*)&DispatchExVtbl);
+ return impl_from_IDispatchEx((IDispatchEx*)disp);
+}
+
+jsdisp_t *to_jsdisp(IDispatch *disp)
+{
+ return disp->lpVtbl == (IDispatchVtbl*)&DispatchExVtbl ? impl_from_IDispatchEx((IDispatchEx*)disp) : NULL;
+}
+
+HRESULT init_dispex(jsdisp_t *dispex, script_ctx_t *ctx, const builtin_info_t *builtin_info, jsdisp_t *prototype)
{
TRACE("%p (%p)\n", dispex, prototype);
- dispex->lpIDispatchExVtbl = &DispatchExVtbl;
+ dispex->IDispatchEx_iface.lpVtbl = &DispatchExVtbl;
dispex->ref = 1;
dispex->builtin_info = builtin_info;
- dispex->props = heap_alloc((dispex->buf_size=4) * sizeof(dispex_prop_t));
+ dispex->props = heap_alloc_zero(sizeof(dispex_prop_t)*(dispex->buf_size=4));
if(!dispex->props)
return E_OUTOFMEMORY;
dispex->prototype = prototype;
if(prototype)
- IDispatchEx_AddRef(_IDispatchEx_(prototype));
+ jsdisp_addref(prototype);
dispex->prop_cnt = 1;
- dispex->props[0].name = NULL;
- dispex->props[0].flags = 0;
if(builtin_info->value_prop.invoke) {
dispex->props[0].type = PROP_BUILTIN;
dispex->props[0].u.p = &builtin_info->value_prop;
NULL
};
-HRESULT create_dispex(script_ctx_t *ctx, const builtin_info_t *builtin_info, DispatchEx *prototype, DispatchEx **dispex)
+HRESULT create_dispex(script_ctx_t *ctx, const builtin_info_t *builtin_info, jsdisp_t *prototype, jsdisp_t **dispex)
{
- DispatchEx *ret;
+ jsdisp_t *ret;
HRESULT hres;
- ret = heap_alloc_zero(sizeof(DispatchEx));
+ ret = heap_alloc_zero(sizeof(jsdisp_t));
if(!ret)
return E_OUTOFMEMORY;
hres = init_dispex(ret, ctx, builtin_info ? builtin_info : &dispex_info, prototype);
- if(FAILED(hres))
+ if(FAILED(hres)) {
+ heap_free(ret);
return hres;
+ }
*dispex = ret;
return S_OK;
}
-HRESULT init_dispex_from_constr(DispatchEx *dispex, script_ctx_t *ctx, const builtin_info_t *builtin_info, DispatchEx *constr)
+void jsdisp_free(jsdisp_t *obj)
{
- DispatchEx *prot = NULL;
+ dispex_prop_t *prop;
+
+ TRACE("(%p)\n", obj);
+
+ for(prop = obj->props; prop < obj->props+obj->prop_cnt; prop++) {
+ if(prop->type == PROP_JSVAL)
+ jsval_release(prop->u.val);
+ heap_free(prop->name);
+ }
+ heap_free(obj->props);
+ script_release(obj->ctx);
+ if(obj->prototype)
+ jsdisp_release(obj->prototype);
+
+ if(obj->builtin_info->destructor)
+ obj->builtin_info->destructor(obj);
+ else
+ heap_free(obj);
+}
+
+#ifdef TRACE_REFCNT
+
+jsdisp_t *jsdisp_addref(jsdisp_t *jsdisp)
+{
+ ULONG ref = ++jsdisp->ref;
+ TRACE("(%p) ref=%d\n", jsdisp, ref);
+ return jsdisp;
+}
+
+void jsdisp_release(jsdisp_t *jsdisp)
+{
+ ULONG ref = --jsdisp->ref;
+
+ TRACE("(%p) ref=%d\n", jsdisp, ref);
+
+ if(!ref)
+ jsdisp_free(jsdisp);
+}
+
+#endif
+
+HRESULT init_dispex_from_constr(jsdisp_t *dispex, script_ctx_t *ctx, const builtin_info_t *builtin_info, jsdisp_t *constr)
+{
+ jsdisp_t *prot = NULL;
dispex_prop_t *prop;
HRESULT hres;
- static const WCHAR constructorW[] = {'c','o','n','s','t','r','u','c','t','o','r'};
static const WCHAR prototypeW[] = {'p','r','o','t','o','t','y','p','e',0};
- hres = find_prop_name_prot(constr, prototypeW, &prop);
- if(SUCCEEDED(hres) && prop) {
- jsexcept_t jsexcept;
- VARIANT var;
+ hres = find_prop_name_prot(constr, string_hash(prototypeW), prototypeW, &prop);
+ if(SUCCEEDED(hres) && prop && prop->type!=PROP_DELETED) {
+ jsval_t val;
- V_VT(&var) = VT_EMPTY;
- memset(&jsexcept, 0, sizeof(jsexcept));
- hres = prop_get(constr, prop, NULL, &var, &jsexcept, NULL/*FIXME*/);
+ hres = prop_get(constr, prop, NULL, &val, NULL);
if(FAILED(hres)) {
ERR("Could not get prototype\n");
return hres;
}
- if(V_VT(&var) == VT_DISPATCH)
- prot = iface_to_jsdisp((IUnknown*)V_DISPATCH(&var));
- VariantClear(&var);
+ if(is_object_instance(val))
+ prot = iface_to_jsdisp((IUnknown*)get_object(val));
+ jsval_release(val);
}
hres = init_dispex(dispex, ctx, builtin_info, prot);
if(prot)
jsdisp_release(prot);
- if(FAILED(hres))
- return hres;
-
- hres = ensure_prop_name(dispex, constructorW, FALSE, 0, &prop);
- if(SUCCEEDED(hres)) {
- jsexcept_t jsexcept;
- VARIANT var;
-
- V_VT(&var) = VT_DISPATCH;
- V_DISPATCH(&var) = (IDispatch*)_IDispatchEx_(constr);
- memset(&jsexcept, 0, sizeof(jsexcept));
- hres = prop_put(dispex, prop, &var, &jsexcept, NULL/*FIXME*/);
- }
- if(FAILED(hres))
- jsdisp_release(dispex);
-
return hres;
}
-DispatchEx *iface_to_jsdisp(IUnknown *iface)
+jsdisp_t *iface_to_jsdisp(IUnknown *iface)
{
- DispatchEx *ret;
+ jsdisp_t *ret;
HRESULT hres;
hres = IUnknown_QueryInterface(iface, &IID_IDispatchJS, (void**)&ret);
return ret;
}
-HRESULT jsdisp_get_id(DispatchEx *jsdisp, const WCHAR *name, DWORD flags, DISPID *id)
+HRESULT jsdisp_get_id(jsdisp_t *jsdisp, const WCHAR *name, DWORD flags, DISPID *id)
{
dispex_prop_t *prop;
HRESULT hres;
if(flags & fdexNameEnsure)
hres = ensure_prop_name(jsdisp, name, TRUE, PROPF_ENUM, &prop);
else
- hres = find_prop_name_prot(jsdisp, name, &prop);
+ hres = find_prop_name_prot(jsdisp, string_hash(name), name, &prop);
if(FAILED(hres))
return hres;
- if(prop) {
+ if(prop && prop->type!=PROP_DELETED) {
*id = prop_to_id(jsdisp, prop);
return S_OK;
}
return DISP_E_UNKNOWNNAME;
}
-HRESULT jsdisp_call_value(DispatchEx *jsthis, WORD flags, DISPPARAMS *dp, VARIANT *retv,
- jsexcept_t *ei, IServiceProvider *caller)
+HRESULT jsdisp_call_value(jsdisp_t *jsfunc, IDispatch *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r)
{
- vdisp_t vdisp;
HRESULT hres;
- set_jsdisp(&vdisp, jsthis);
- hres = jsthis->builtin_info->value_prop.invoke(jsthis->ctx, &vdisp, flags, dp, retv, ei, caller);
- vdisp_release(&vdisp);
+ if(is_class(jsfunc, JSCLASS_FUNCTION)) {
+ hres = Function_invoke(jsfunc, jsthis, flags, argc, argv, r);
+ }else {
+ vdisp_t vdisp;
+
+ set_disp(&vdisp, jsthis);
+ hres = jsfunc->builtin_info->value_prop.invoke(jsfunc->ctx, &vdisp, flags, argc, argv, r);
+ vdisp_release(&vdisp);
+ }
return hres;
}
-HRESULT jsdisp_call(DispatchEx *disp, DISPID id, WORD flags, DISPPARAMS *dp, VARIANT *retv,
- jsexcept_t *ei, IServiceProvider *caller)
+HRESULT jsdisp_call(jsdisp_t *disp, DISPID id, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r)
{
dispex_prop_t *prop;
- memset(ei, 0, sizeof(*ei));
- if(retv)
- V_VT(retv) = VT_EMPTY;
-
prop = get_prop(disp, id);
if(!prop)
return DISP_E_MEMBERNOTFOUND;
- return invoke_prop_func(disp, disp, prop, flags, dp, retv, ei, caller);
+ return invoke_prop_func(disp, to_disp(disp), prop, flags, argc, argv, r, NULL);
}
-HRESULT jsdisp_call_name(DispatchEx *disp, const WCHAR *name, WORD flags, DISPPARAMS *dp, VARIANT *retv,
- jsexcept_t *ei, IServiceProvider *caller)
+HRESULT jsdisp_call_name(jsdisp_t *disp, const WCHAR *name, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r)
{
dispex_prop_t *prop;
HRESULT hres;
- hres = find_prop_name_prot(disp, name, &prop);
+ hres = find_prop_name_prot(disp, string_hash(name), name, &prop);
if(FAILED(hres))
return hres;
- memset(ei, 0, sizeof(*ei));
- if(retv)
- V_VT(retv) = VT_EMPTY;
+ return invoke_prop_func(disp, to_disp(disp), prop, flags, argc, argv, r, NULL);
+}
+
+HRESULT disp_call(script_ctx_t *ctx, IDispatch *disp, DISPID id, WORD flags, unsigned argc, jsval_t *argv, jsval_t *ret)
+{
+ IDispatchEx *dispex;
+ jsdisp_t *jsdisp;
+ VARIANT buf[6], retv;
+ DISPPARAMS dp;
+ unsigned i;
+ HRESULT hres;
+
+ jsdisp = iface_to_jsdisp((IUnknown*)disp);
+ if(jsdisp) {
+ if(flags & DISPATCH_PROPERTYPUT) {
+ FIXME("disp_call(propput) on builtin object\n");
+ return E_FAIL;
+ }
+
+ hres = jsdisp_call(jsdisp, id, flags, argc, argv, ret);
+ jsdisp_release(jsdisp);
+ return hres;
+ }
+
+ if(ret && argc)
+ flags |= DISPATCH_PROPERTYGET;
+
+ dp.cArgs = argc;
+
+ if(flags & DISPATCH_PROPERTYPUT) {
+ static DISPID propput_dispid = DISPID_PROPERTYPUT;
+
+ dp.cNamedArgs = 1;
+ dp.rgdispidNamedArgs = &propput_dispid;
+ }else {
+ dp.cNamedArgs = 0;
+ dp.rgdispidNamedArgs = NULL;
+ }
+
+ if(argc > 6) {
+ dp.rgvarg = heap_alloc(argc*sizeof(VARIANT));
+ if(!dp.rgvarg)
+ return E_OUTOFMEMORY;
+ }else {
+ dp.rgvarg = buf;
+ }
+
+ for(i=0; i<argc; i++) {
+ hres = jsval_to_variant(argv[i], dp.rgvarg+argc-i-1);
+ if(FAILED(hres)) {
+ while(i--)
+ VariantClear(dp.rgvarg+argc-i-1);
+ if(dp.rgvarg != buf)
+ heap_free(dp.rgvarg);
+ return hres;
+ }
+ }
+
+ V_VT(&retv) = VT_EMPTY;
+ clear_ei(ctx);
+ hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
+ if(SUCCEEDED(hres)) {
+ hres = IDispatchEx_InvokeEx(dispex, id, ctx->lcid, flags, &dp, ret ? &retv : NULL, &ctx->ei.ei,
+ &ctx->jscaller->IServiceProvider_iface);
+ IDispatchEx_Release(dispex);
+ }else {
+ UINT err = 0;
+
+ if(flags == DISPATCH_CONSTRUCT) {
+ WARN("IDispatch cannot be constructor\n");
+ return DISP_E_MEMBERNOTFOUND;
+ }
+
+ TRACE("using IDispatch\n");
+ hres = IDispatch_Invoke(disp, id, &IID_NULL, ctx->lcid, flags, &dp, ret ? &retv : NULL, &ctx->ei.ei, &err);
+ }
- return invoke_prop_func(disp, disp, prop, flags, dp, retv, ei, caller);
+ for(i=0; i<argc; i++)
+ VariantClear(dp.rgvarg+argc-i-1);
+ if(dp.rgvarg != buf)
+ heap_free(dp.rgvarg);
+ if(FAILED(hres))
+ return hres;
+
+ if(ret) {
+ hres = variant_to_jsval(&retv, ret);
+ VariantClear(&retv);
+ }
+ return hres;
}
-HRESULT disp_call(script_ctx_t *ctx, IDispatch *disp, DISPID id, WORD flags, DISPPARAMS *dp, VARIANT *retv,
- jsexcept_t *ei, IServiceProvider *caller)
+HRESULT disp_call_value(script_ctx_t *ctx, IDispatch *disp, IDispatch *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- DispatchEx *jsdisp;
+ jsdisp_t *jsdisp;
IDispatchEx *dispex;
+ VARIANT buf[6], retv;
+ DISPPARAMS dp;
+ unsigned i;
HRESULT hres;
jsdisp = iface_to_jsdisp((IUnknown*)disp);
if(jsdisp) {
- hres = jsdisp_call(jsdisp, id, flags, dp, retv, ei, caller);
+ if(flags & DISPATCH_PROPERTYPUT) {
+ FIXME("disp_call(propput) on builtin object\n");
+ return E_FAIL;
+ }
+
+ hres = jsdisp_call_value(jsdisp, jsthis, flags, argc, argv, r);
jsdisp_release(jsdisp);
return hres;
}
- memset(ei, 0, sizeof(*ei));
+ if(r && argc)
+ flags |= DISPATCH_PROPERTYGET;
- if(retv)
- V_VT(retv) = VT_EMPTY;
hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
if(FAILED(hres)) {
+ TRACE("using IDispatch\n");
+ dispex = NULL;
+ jsthis = NULL;
+ }
+
+ if(jsthis) {
+ static DISPID this_id = DISPID_THIS;
+
+ dp.cArgs = argc+1;
+ dp.cNamedArgs = 1;
+ dp.rgdispidNamedArgs = &this_id;
+ }else {
+ dp.cArgs = argc;
+ dp.cNamedArgs = 0;
+ dp.rgdispidNamedArgs = NULL;
+ }
+
+ if(dp.cArgs > sizeof(buf)/sizeof(*buf)) {
+ dp.rgvarg = heap_alloc(dp.cArgs*sizeof(VARIANT));
+ if(!dp.rgvarg) {
+ if(dispex)
+ IDispatchEx_Release(dispex);
+ return E_OUTOFMEMORY;
+ }
+ }else {
+ dp.rgvarg = buf;
+ }
+
+ for(i=0; i<argc; i++) {
+ hres = jsval_to_variant(argv[i], dp.rgvarg+dp.cArgs-i-1);
+ if(FAILED(hres)) {
+ while(i--)
+ VariantClear(dp.rgvarg+dp.cArgs-i-1);
+ if(dp.rgvarg != buf)
+ heap_free(dp.rgvarg);
+ if(dispex)
+ IDispatchEx_Release(dispex);
+ return hres;
+ }
+ }
+ if(jsthis) {
+ V_VT(dp.rgvarg) = VT_DISPATCH;
+ V_DISPATCH(dp.rgvarg) = jsthis;
+ }
+
+ V_VT(&retv) = VT_EMPTY;
+ clear_ei(ctx);
+ if(dispex) {
+ hres = IDispatchEx_InvokeEx(dispex, DISPID_VALUE, ctx->lcid, flags, &dp, r ? &retv : NULL, &ctx->ei.ei,
+ &ctx->jscaller->IServiceProvider_iface);
+ IDispatchEx_Release(dispex);
+ }else {
UINT err = 0;
if(flags == DISPATCH_CONSTRUCT) {
return DISP_E_MEMBERNOTFOUND;
}
- TRACE("using IDispatch\n");
- return IDispatch_Invoke(disp, id, &IID_NULL, ctx->lcid, flags, dp, retv, &ei->ei, &err);
+ hres = IDispatch_Invoke(disp, DISPID_VALUE, &IID_NULL, ctx->lcid, flags, &dp, r ? &retv : NULL, &ctx->ei.ei, &err);
}
- hres = IDispatchEx_InvokeEx(dispex, id, ctx->lcid, flags, dp, retv, &ei->ei, caller);
- IDispatchEx_Release(dispex);
+ for(i=0; i<argc; i++)
+ VariantClear(dp.rgvarg+dp.cArgs-i-1);
+ if(dp.rgvarg != buf)
+ heap_free(dp.rgvarg);
+ if(FAILED(hres))
+ return hres;
+
+ if(!r)
+ return S_OK;
+ hres = variant_to_jsval(&retv, r);
+ VariantClear(&retv);
return hres;
}
-HRESULT jsdisp_propput_name(DispatchEx *obj, const WCHAR *name, VARIANT *val, jsexcept_t *ei, IServiceProvider *caller)
+HRESULT jsdisp_propput(jsdisp_t *obj, const WCHAR *name, DWORD flags, jsval_t val)
{
dispex_prop_t *prop;
HRESULT hres;
- hres = ensure_prop_name(obj, name, FALSE, PROPF_ENUM, &prop);
+ hres = ensure_prop_name(obj, name, FALSE, flags, &prop);
if(FAILED(hres))
return hres;
- return prop_put(obj, prop, val, ei, caller);
+ return prop_put(obj, prop, val, NULL);
}
-HRESULT jsdisp_propput_const(DispatchEx *obj, const WCHAR *name, VARIANT *val)
+HRESULT jsdisp_propput_name(jsdisp_t *obj, const WCHAR *name, jsval_t val)
+{
+ return jsdisp_propput(obj, name, PROPF_ENUM, val);
+}
+
+HRESULT jsdisp_propput_const(jsdisp_t *obj, const WCHAR *name, jsval_t val)
{
dispex_prop_t *prop;
HRESULT hres;
- hres = ensure_prop_name(obj, name, FALSE, PROPF_ENUM|PROPF_CONST, &prop);
+ hres = ensure_prop_name(obj, name, FALSE, PROPF_CONST, &prop);
if(FAILED(hres))
return hres;
- return VariantCopy(&prop->u.var, val);
+ return jsval_copy(val, &prop->u.val);
}
-HRESULT jsdisp_propput_idx(DispatchEx *obj, DWORD idx, VARIANT *val, jsexcept_t *ei, IServiceProvider *caller)
+HRESULT jsdisp_propput_dontenum(jsdisp_t *obj, const WCHAR *name, jsval_t val)
+{
+ return jsdisp_propput(obj, name, 0, val);
+}
+
+HRESULT jsdisp_propput_idx(jsdisp_t *obj, DWORD idx, jsval_t val)
{
WCHAR buf[12];
static const WCHAR formatW[] = {'%','d',0};
sprintfW(buf, formatW, idx);
- return jsdisp_propput_name(obj, buf, val, ei, caller);
+ return jsdisp_propput_name(obj, buf, val);
}
-HRESULT disp_propput(script_ctx_t *ctx, IDispatch *disp, DISPID id, VARIANT *val, jsexcept_t *ei, IServiceProvider *caller)
+HRESULT disp_propput(script_ctx_t *ctx, IDispatch *disp, DISPID id, jsval_t val)
{
- DispatchEx *jsdisp;
+ jsdisp_t *jsdisp;
HRESULT hres;
jsdisp = iface_to_jsdisp((IUnknown*)disp);
prop = get_prop(jsdisp, id);
if(prop)
- hres = prop_put(jsdisp, prop, val, ei, caller);
+ hres = prop_put(jsdisp, prop, val, NULL);
else
hres = DISP_E_MEMBERNOTFOUND;
jsdisp_release(jsdisp);
}else {
DISPID dispid = DISPID_PROPERTYPUT;
- DISPPARAMS dp = {val, &dispid, 1, 1};
+ VARIANT var;
+ DISPPARAMS dp = {&var, &dispid, 1, 1};
IDispatchEx *dispex;
+ hres = jsval_to_variant(val, &var);
+ if(FAILED(hres))
+ return hres;
+
+ clear_ei(ctx);
hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
if(SUCCEEDED(hres)) {
- hres = IDispatchEx_InvokeEx(dispex, id, ctx->lcid, DISPATCH_PROPERTYPUT, &dp, NULL, &ei->ei, caller);
+ hres = IDispatchEx_InvokeEx(dispex, id, ctx->lcid, DISPATCH_PROPERTYPUT, &dp, NULL, &ctx->ei.ei,
+ &ctx->jscaller->IServiceProvider_iface);
IDispatchEx_Release(dispex);
}else {
ULONG err = 0;
TRACE("using IDispatch\n");
- hres = IDispatch_Invoke(disp, id, &IID_NULL, ctx->lcid, DISPATCH_PROPERTYPUT, &dp, NULL, &ei->ei, &err);
+ hres = IDispatch_Invoke(disp, id, &IID_NULL, ctx->lcid, DISPATCH_PROPERTYPUT, &dp, NULL, &ctx->ei.ei, &err);
}
+
+ VariantClear(&var);
}
return hres;
}
-HRESULT jsdisp_propget_name(DispatchEx *obj, const WCHAR *name, VARIANT *var, jsexcept_t *ei, IServiceProvider *caller)
+HRESULT jsdisp_propget_name(jsdisp_t *obj, const WCHAR *name, jsval_t *val)
{
DISPPARAMS dp = {NULL, NULL, 0, 0};
dispex_prop_t *prop;
HRESULT hres;
- hres = find_prop_name_prot(obj, name, &prop);
+ hres = find_prop_name_prot(obj, string_hash(name), name, &prop);
if(FAILED(hres))
return hres;
- V_VT(var) = VT_EMPTY;
- if(!prop)
+ if(!prop || prop->type==PROP_DELETED) {
+ *val = jsval_undefined();
return S_OK;
+ }
- return prop_get(obj, prop, &dp, var, ei, caller);
+ return prop_get(obj, prop, &dp, val, NULL);
}
-HRESULT jsdisp_get_idx(DispatchEx *obj, DWORD idx, VARIANT *var, jsexcept_t *ei, IServiceProvider *caller)
+HRESULT jsdisp_get_idx(jsdisp_t *obj, DWORD idx, jsval_t *r)
{
WCHAR name[12];
DISPPARAMS dp = {NULL, NULL, 0, 0};
sprintfW(name, formatW, idx);
- hres = find_prop_name_prot(obj, name, &prop);
+ hres = find_prop_name_prot(obj, string_hash(name), name, &prop);
if(FAILED(hres))
return hres;
- V_VT(var) = VT_EMPTY;
- if(!prop)
+ if(!prop || prop->type==PROP_DELETED) {
+ *r = jsval_undefined();
return DISP_E_UNKNOWNNAME;
+ }
- return prop_get(obj, prop, &dp, var, ei, caller);
+ return prop_get(obj, prop, &dp, r, NULL);
}
-HRESULT jsdisp_propget(DispatchEx *jsdisp, DISPID id, VARIANT *val, jsexcept_t *ei, IServiceProvider *caller)
+HRESULT jsdisp_propget(jsdisp_t *jsdisp, DISPID id, jsval_t *val)
{
DISPPARAMS dp = {NULL,NULL,0,0};
dispex_prop_t *prop;
if(!prop)
return DISP_E_MEMBERNOTFOUND;
- V_VT(val) = VT_EMPTY;
- return prop_get(jsdisp, prop, &dp, val, ei, caller);
+ return prop_get(jsdisp, prop, &dp, val, NULL);
}
-HRESULT disp_propget(script_ctx_t *ctx, IDispatch *disp, DISPID id, VARIANT *val, jsexcept_t *ei, IServiceProvider *caller)
+HRESULT disp_propget(script_ctx_t *ctx, IDispatch *disp, DISPID id, jsval_t *val)
{
DISPPARAMS dp = {NULL,NULL,0,0};
IDispatchEx *dispex;
- DispatchEx *jsdisp;
+ jsdisp_t *jsdisp;
+ VARIANT var;
HRESULT hres;
jsdisp = iface_to_jsdisp((IUnknown*)disp);
if(jsdisp) {
- hres = jsdisp_propget(jsdisp, id, val, ei, caller);
+ hres = jsdisp_propget(jsdisp, id, val);
jsdisp_release(jsdisp);
return hres;
}
+ V_VT(&var) = VT_EMPTY;
+ clear_ei(ctx);
hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
- if(FAILED(hres)) {
+ if(SUCCEEDED(hres)) {
+ hres = IDispatchEx_InvokeEx(dispex, id, ctx->lcid, INVOKE_PROPERTYGET, &dp, &var, &ctx->ei.ei,
+ &ctx->jscaller->IServiceProvider_iface);
+ IDispatchEx_Release(dispex);
+ }else {
ULONG err = 0;
TRACE("using IDispatch\n");
- return IDispatch_Invoke(disp, id, &IID_NULL, ctx->lcid, INVOKE_PROPERTYGET, &dp, val, &ei->ei, &err);
+ hres = IDispatch_Invoke(disp, id, &IID_NULL, ctx->lcid, INVOKE_PROPERTYGET, &dp, &var, &ctx->ei.ei, &err);
}
+ if(FAILED(hres))
+ return hres;
- hres = IDispatchEx_InvokeEx(dispex, id, ctx->lcid, INVOKE_PROPERTYGET, &dp, val, &ei->ei, caller);
- IDispatchEx_Release(dispex);
-
+ hres = variant_to_jsval(&var, val);
+ VariantClear(&var);
return hres;
}
-HRESULT jsdisp_delete_idx(DispatchEx *obj, DWORD idx)
+HRESULT jsdisp_delete_idx(jsdisp_t *obj, DWORD idx)
{
static const WCHAR formatW[] = {'%','d',0};
WCHAR buf[12];
dispex_prop_t *prop;
+ BOOL b;
HRESULT hres;
sprintfW(buf, formatW, idx);
- hres = find_prop_name(obj, buf, &prop);
+ hres = find_prop_name(obj, string_hash(buf), buf, &prop);
if(FAILED(hres) || !prop)
return hres;
- return delete_prop(prop);
+ return delete_prop(prop, &b);
+}
+
+HRESULT disp_delete(IDispatch *disp, DISPID id, BOOL *ret)
+{
+ IDispatchEx *dispex;
+ jsdisp_t *jsdisp;
+ HRESULT hres;
+
+ jsdisp = iface_to_jsdisp((IUnknown*)disp);
+ if(jsdisp) {
+ dispex_prop_t *prop;
+
+ prop = get_prop(jsdisp, id);
+ if(prop)
+ hres = delete_prop(prop, ret);
+ else
+ hres = DISP_E_MEMBERNOTFOUND;
+
+ jsdisp_release(jsdisp);
+ return hres;
+ }
+
+ hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
+ if(FAILED(hres)) {
+ *ret = FALSE;
+ return S_OK;
+ }
+
+ hres = IDispatchEx_DeleteMemberByDispID(dispex, id);
+ IDispatchEx_Release(dispex);
+ if(FAILED(hres))
+ return hres;
+
+ *ret = hres == S_OK;
+ return S_OK;
+}
+
+HRESULT disp_delete_name(script_ctx_t *ctx, IDispatch *disp, jsstr_t *name, BOOL *ret)
+{
+ IDispatchEx *dispex;
+ jsdisp_t *jsdisp;
+ BSTR bstr;
+ HRESULT hres;
+
+ jsdisp = iface_to_jsdisp((IUnknown*)disp);
+ if(jsdisp) {
+ dispex_prop_t *prop;
+
+ hres = find_prop_name(jsdisp, string_hash(name->str), name->str, &prop);
+ if(prop) {
+ hres = delete_prop(prop, ret);
+ }else {
+ *ret = TRUE;
+ hres = S_OK;
+ }
+
+ jsdisp_release(jsdisp);
+ return hres;
+ }
+
+ bstr = SysAllocStringLen(NULL, jsstr_length(name));
+ if(!bstr)
+ return E_OUTOFMEMORY;
+ jsstr_flush(name, bstr);
+
+ hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
+ if(SUCCEEDED(hres)) {
+ hres = IDispatchEx_DeleteMemberByName(dispex, bstr, make_grfdex(ctx, fdexNameCaseSensitive));
+ if(SUCCEEDED(hres))
+ *ret = hres == S_OK;
+ IDispatchEx_Release(dispex);
+ }else {
+ DISPID id;
+
+ hres = IDispatch_GetIDsOfNames(disp, &IID_NULL, &bstr, 1, 0, &id);
+ if(SUCCEEDED(hres)) {
+ /* Property exists and we can't delete it from pure IDispatch interface, so return false. */
+ *ret = FALSE;
+ }else if(hres == DISP_E_UNKNOWNNAME) {
+ /* Property doesn't exist, so nothing to delete */
+ *ret = TRUE;
+ hres = S_OK;
+ }
+ }
+
+ SysFreeString(bstr);
+ return hres;
+}
+
+HRESULT jsdisp_is_own_prop(jsdisp_t *obj, const WCHAR *name, BOOL *ret)
+{
+ dispex_prop_t *prop;
+ HRESULT hres;
+
+ hres = find_prop_name(obj, string_hash(name), name, &prop);
+ if(FAILED(hres))
+ return hres;
+
+ *ret = prop && (prop->type == PROP_JSVAL || prop->type == PROP_BUILTIN);
+ return S_OK;
+}
+
+HRESULT jsdisp_is_enumerable(jsdisp_t *obj, const WCHAR *name, BOOL *ret)
+{
+ dispex_prop_t *prop;
+ HRESULT hres;
+
+ hres = find_prop_name(obj, string_hash(name), name, &prop);
+ if(FAILED(hres))
+ return hres;
+
+ *ret = prop && (prop->flags & PROPF_ENUM) && prop->type != PROP_PROTREF;
+ return S_OK;
}
/*
- * Copyright 2008 Jacek Caban for CodeWeavers
+ * Copyright 2008,2011 Jacek Caban for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
#include <wine/port.h>
//#include <math.h>
+#include <assert.h>
#include "jscript.h"
#include "engine.h"
WINE_DEFAULT_DEBUG_CHANNEL(jscript);
-#define EXPR_NOVAL 0x0001
-#define EXPR_NEWREF 0x0002
-#define EXPR_STRREF 0x0004
+static const WCHAR booleanW[] = {'b','o','o','l','e','a','n',0};
+static const WCHAR functionW[] = {'f','u','n','c','t','i','o','n',0};
+static const WCHAR numberW[] = {'n','u','m','b','e','r',0};
+static const WCHAR objectW[] = {'o','b','j','e','c','t',0};
+static const WCHAR stringW[] = {'s','t','r','i','n','g',0};
+static const WCHAR undefinedW[] = {'u','n','d','e','f','i','n','e','d',0};
+static const WCHAR unknownW[] = {'u','n','k','n','o','w','n',0};
-static inline HRESULT stat_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
+struct _except_frame_t {
+ unsigned stack_top;
+ scope_chain_t *scope;
+ unsigned catch_off;
+ BSTR ident;
+
+ except_frame_t *next;
+};
+
+static HRESULT stack_push(exec_ctx_t *ctx, jsval_t v)
+{
+ if(!ctx->stack_size) {
+ ctx->stack = heap_alloc(16*sizeof(*ctx->stack));
+ if(!ctx->stack)
+ return E_OUTOFMEMORY;
+ ctx->stack_size = 16;
+ }else if(ctx->stack_size == ctx->top) {
+ jsval_t *new_stack;
+
+ new_stack = heap_realloc(ctx->stack, ctx->stack_size*2*sizeof(*new_stack));
+ if(!new_stack) {
+ jsval_release(v);
+ return E_OUTOFMEMORY;
+ }
+
+ ctx->stack = new_stack;
+ ctx->stack_size *= 2;
+ }
+
+ ctx->stack[ctx->top++] = v;
+ return S_OK;
+}
+
+static inline HRESULT stack_push_string(exec_ctx_t *ctx, const WCHAR *str)
+{
+ jsstr_t *v;
+
+ v = jsstr_alloc(str);
+ if(!v)
+ return E_OUTOFMEMORY;
+
+ return stack_push(ctx, jsval_string(v));
+}
+
+static HRESULT stack_push_objid(exec_ctx_t *ctx, IDispatch *disp, DISPID id)
+{
+ HRESULT hres;
+
+ hres = stack_push(ctx, jsval_disp(disp));
+ if(FAILED(hres))
+ return hres;
+
+ return stack_push(ctx, jsval_number(id));
+}
+
+static inline jsval_t stack_top(exec_ctx_t *ctx)
+{
+ assert(ctx->top);
+ return ctx->stack[ctx->top-1];
+}
+
+static inline jsval_t stack_topn(exec_ctx_t *ctx, unsigned n)
+{
+ assert(ctx->top > n);
+ return ctx->stack[ctx->top-1-n];
+}
+
+static inline jsval_t *stack_args(exec_ctx_t *ctx, unsigned n)
+{
+ if(!n)
+ return NULL;
+ assert(ctx->top > n-1);
+ return ctx->stack + ctx->top-n;
+}
+
+static inline jsval_t stack_pop(exec_ctx_t *ctx)
+{
+ assert(ctx->top);
+ return ctx->stack[--ctx->top];
+}
+
+static void stack_popn(exec_ctx_t *ctx, unsigned n)
+{
+ while(n--)
+ jsval_release(stack_pop(ctx));
+}
+
+static HRESULT stack_pop_number(exec_ctx_t *ctx, double *r)
+{
+ jsval_t v;
+ HRESULT hres;
+
+ v = stack_pop(ctx);
+ hres = to_number(ctx->script, v, r);
+ jsval_release(v);
+ return hres;
+}
+
+static HRESULT stack_pop_object(exec_ctx_t *ctx, IDispatch **r)
+{
+ jsval_t v;
+ HRESULT hres;
+
+ v = stack_pop(ctx);
+ if(is_object_instance(v)) {
+ if(!get_object(v))
+ return throw_type_error(ctx->script, JS_E_OBJECT_REQUIRED, NULL);
+ *r = get_object(v);
+ return S_OK;
+ }
+
+ hres = to_object(ctx->script, v, r);
+ jsval_release(v);
+ return hres;
+}
+
+static inline HRESULT stack_pop_int(exec_ctx_t *ctx, INT *r)
+{
+ return to_int32(ctx->script, stack_pop(ctx), r);
+}
+
+static inline HRESULT stack_pop_uint(exec_ctx_t *ctx, DWORD *r)
+{
+ return to_uint32(ctx->script, stack_pop(ctx), r);
+}
+
+static inline IDispatch *stack_pop_objid(exec_ctx_t *ctx, DISPID *id)
{
- return stat->eval(ctx, stat, rt, ret);
+ assert(is_number(stack_top(ctx)) && is_object_instance(stack_topn(ctx, 1)));
+
+ *id = get_number(stack_pop(ctx));
+ return get_object(stack_pop(ctx));
}
-static inline HRESULT expr_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
+static inline IDispatch *stack_topn_objid(exec_ctx_t *ctx, unsigned n, DISPID *id)
{
- return _expr->eval(ctx, _expr, flags, ei, ret);
+ assert(is_number(stack_topn(ctx, n)) && is_object_instance(stack_topn(ctx, n+1)));
+
+ *id = get_number(stack_topn(ctx, n));
+ return get_object(stack_topn(ctx, n+1));
}
static void exprval_release(exprval_t *val)
{
switch(val->type) {
- case EXPRVAL_VARIANT:
- if(V_VT(&val->u.var) != VT_EMPTY)
- VariantClear(&val->u.var);
+ case EXPRVAL_JSVAL:
+ jsval_release(val->u.val);
return;
case EXPRVAL_IDREF:
if(val->u.idref.disp)
IDispatch_Release(val->u.idref.disp);
return;
- case EXPRVAL_NAMEREF:
- if(val->u.nameref.disp)
- IDispatch_Release(val->u.nameref.disp);
- SysFreeString(val->u.nameref.name);
- return;
case EXPRVAL_INVALID:
- SysFreeString(val->u.identifier);
+ return;
}
}
/* ECMA-262 3rd Edition 8.7.1 */
-static HRESULT exprval_value(script_ctx_t *ctx, exprval_t *val, jsexcept_t *ei, VARIANT *ret)
+static HRESULT exprval_to_value(script_ctx_t *ctx, exprval_t *val, jsval_t *ret)
{
- V_VT(ret) = VT_EMPTY;
-
switch(val->type) {
- case EXPRVAL_VARIANT:
- return VariantCopy(ret, &val->u.var);
+ case EXPRVAL_JSVAL:
+ *ret = val->u.val;
+ val->u.val = jsval_undefined();
+ return S_OK;
case EXPRVAL_IDREF:
if(!val->u.idref.disp) {
FIXME("throw ReferenceError\n");
return E_FAIL;
}
- return disp_propget(ctx, val->u.idref.disp, val->u.idref.id, ret, ei, NULL/*FIXME*/);
- case EXPRVAL_NAMEREF:
- break;
+ return disp_propget(ctx, val->u.idref.disp, val->u.idref.id, ret);
case EXPRVAL_INVALID:
- return throw_type_error(ctx, ei, IDS_UNDEFINED, val->u.identifier);
+ assert(0);
}
ERR("type %d\n", val->type);
return E_FAIL;
}
-static HRESULT exprval_to_value(script_ctx_t *ctx, exprval_t *val, jsexcept_t *ei, VARIANT *ret)
-{
- if(val->type == EXPRVAL_VARIANT) {
- *ret = val->u.var;
- V_VT(&val->u.var) = VT_EMPTY;
- return S_OK;
- }
-
- return exprval_value(ctx, val, ei, ret);
-}
-
-static HRESULT exprval_to_boolean(script_ctx_t *ctx, exprval_t *exprval, jsexcept_t *ei, VARIANT_BOOL *b)
-{
- if(exprval->type != EXPRVAL_VARIANT) {
- VARIANT val;
- HRESULT hres;
-
- hres = exprval_to_value(ctx, exprval, ei, &val);
- if(FAILED(hres))
- return hres;
-
- hres = to_boolean(&val, b);
- VariantClear(&val);
- return hres;
- }
-
- return to_boolean(&exprval->u.var, b);
-}
-
-static void exprval_init(exprval_t *val)
-{
- val->type = EXPRVAL_VARIANT;
- V_VT(&val->u.var) = VT_EMPTY;
-}
-
static void exprval_set_idref(exprval_t *val, IDispatch *disp, DISPID id)
{
val->type = EXPRVAL_IDREF;
IDispatch_AddRef(disp);
}
-HRESULT scope_push(scope_chain_t *scope, DispatchEx *obj, scope_chain_t **ret)
+HRESULT scope_push(scope_chain_t *scope, jsdisp_t *jsobj, IDispatch *obj, scope_chain_t **ret)
{
scope_chain_t *new_scope;
new_scope->ref = 1;
- IDispatchEx_AddRef(_IDispatchEx_(obj));
+ IDispatch_AddRef(obj);
+ new_scope->jsobj = jsobj;
new_scope->obj = obj;
if(scope) {
scope_release(tmp);
}
+void clear_ei(script_ctx_t *ctx)
+{
+ memset(&ctx->ei.ei, 0, sizeof(ctx->ei.ei));
+ jsval_release(ctx->ei.val);
+ ctx->ei.val = jsval_undefined();
+}
+
void scope_release(scope_chain_t *scope)
{
if(--scope->ref)
if(scope->next)
scope_release(scope->next);
- jsdisp_release(scope->obj);
+ IDispatch_Release(scope->obj);
heap_free(scope);
}
-HRESULT create_exec_ctx(script_ctx_t *script_ctx, IDispatch *this_obj, DispatchEx *var_disp,
- scope_chain_t *scope, exec_ctx_t **ret)
+HRESULT create_exec_ctx(script_ctx_t *script_ctx, IDispatch *this_obj, jsdisp_t *var_disp,
+ scope_chain_t *scope, BOOL is_global, exec_ctx_t **ret)
{
exec_ctx_t *ctx;
return E_OUTOFMEMORY;
ctx->ref = 1;
+ ctx->is_global = is_global;
+ ctx->ret = jsval_undefined();
+
+ /* ECMA-262 3rd Edition 11.2.3.7 */
+ if(this_obj) {
+ jsdisp_t *jsthis;
+
+ jsthis = iface_to_jsdisp((IUnknown*)this_obj);
+ if(jsthis) {
+ if(jsthis->builtin_info->class == JSCLASS_GLOBAL || jsthis->builtin_info->class == JSCLASS_NONE)
+ this_obj = NULL;
+ jsdisp_release(jsthis);
+ }
+ }
if(this_obj)
ctx->this_obj = this_obj;
else if(script_ctx->host_global)
ctx->this_obj = script_ctx->host_global;
else
- ctx->this_obj = (IDispatch*)_IDispatchEx_(script_ctx->global);
+ ctx->this_obj = to_disp(script_ctx->global);
IDispatch_AddRef(ctx->this_obj);
- IDispatchEx_AddRef(_IDispatchEx_(var_disp));
+ jsdisp_addref(var_disp);
ctx->var_disp = var_disp;
+ script_addref(script_ctx);
+ ctx->script = script_ctx;
+
if(scope) {
scope_addref(scope);
ctx->scope_chain = scope;
jsdisp_release(ctx->var_disp);
if(ctx->this_obj)
IDispatch_Release(ctx->this_obj);
+ if(ctx->script)
+ script_release(ctx->script);
+ jsval_release(ctx->ret);
+ heap_free(ctx->stack);
heap_free(ctx);
}
-static HRESULT disp_get_id(script_ctx_t *ctx, IDispatch *disp, BSTR name, DWORD flags, DISPID *id)
+static HRESULT disp_get_id(script_ctx_t *ctx, IDispatch *disp, WCHAR *name, BSTR name_bstr, DWORD flags, DISPID *id)
{
IDispatchEx *dispex;
+ jsdisp_t *jsdisp;
+ BSTR bstr;
HRESULT hres;
- hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
- if(FAILED(hres)) {
- TRACE("unsing IDispatch\n");
+ jsdisp = iface_to_jsdisp((IUnknown*)disp);
+ if(jsdisp) {
+ hres = jsdisp_get_id(jsdisp, name, flags, id);
+ jsdisp_release(jsdisp);
+ return hres;
+ }
- *id = 0;
- return IDispatch_GetIDsOfNames(disp, &IID_NULL, &name, 1, 0, id);
+ if(name_bstr) {
+ bstr = name_bstr;
+ }else {
+ bstr = SysAllocString(name);
+ if(!bstr)
+ return E_OUTOFMEMORY;
}
*id = 0;
- hres = IDispatchEx_GetDispID(dispex, name, make_grfdex(ctx, flags|fdexNameCaseSensitive), id);
- IDispatchEx_Release(dispex);
- return hres;
-}
-
-/* ECMA-262 3rd Edition 8.7.2 */
-static HRESULT put_value(script_ctx_t *ctx, exprval_t *ref, VARIANT *v, jsexcept_t *ei)
-{
- if(ref->type != EXPRVAL_IDREF)
- return throw_reference_error(ctx, ei, IDS_ILLEGAL_ASSIGN, NULL);
+ hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
+ if(SUCCEEDED(hres)) {
+ hres = IDispatchEx_GetDispID(dispex, bstr, make_grfdex(ctx, flags|fdexNameCaseSensitive), id);
+ IDispatchEx_Release(dispex);
+ }else {
+ TRACE("using IDispatch\n");
+ hres = IDispatch_GetIDsOfNames(disp, &IID_NULL, &name, 1, 0, id);
+ }
- return disp_propput(ctx, ref->u.idref.disp, ref->u.idref.id, v, ei, NULL/*FIXME*/);
+ if(name_bstr != bstr)
+ SysFreeString(bstr);
+ return hres;
}
-static inline BOOL is_null(const VARIANT *v)
+static inline BOOL var_is_null(const VARIANT *v)
{
return V_VT(v) == VT_NULL || (V_VT(v) == VT_DISPATCH && !V_DISPATCH(v));
}
}
/* ECMA-262 3rd Edition 11.9.6 */
-static HRESULT equal2_values(VARIANT *lval, VARIANT *rval, BOOL *ret)
+static HRESULT equal2_values(jsval_t lval, jsval_t rval, BOOL *ret)
{
+ jsval_type_t type = jsval_type(lval);
+
TRACE("\n");
- if(V_VT(lval) != V_VT(rval)) {
- if(is_num_vt(V_VT(lval)) && is_num_vt(V_VT(rval)))
- *ret = num_val(lval) == num_val(rval);
- else if(is_null(lval))
- *ret = is_null(rval);
+ if(type != jsval_type(rval)) {
+ if(is_null_instance(lval))
+ *ret = is_null_instance(rval);
else
*ret = FALSE;
return S_OK;
}
- switch(V_VT(lval)) {
- case VT_EMPTY:
- case VT_NULL:
- *ret = VARIANT_TRUE;
- break;
- case VT_I4:
- *ret = V_I4(lval) == V_I4(rval);
+ switch(type) {
+ case JSV_UNDEFINED:
+ case JSV_NULL:
+ *ret = TRUE;
break;
- case VT_R8:
- *ret = V_R8(lval) == V_R8(rval);
+ case JSV_OBJECT:
+ return disp_cmp(get_object(lval), get_object(rval), ret);
+ case JSV_STRING:
+ *ret = jsstr_eq(get_string(lval), get_string(rval));
break;
- case VT_BSTR:
- if(!V_BSTR(lval))
- *ret = SysStringLen(V_BSTR(rval))?FALSE:TRUE;
- else if(!V_BSTR(rval))
- *ret = SysStringLen(V_BSTR(lval))?FALSE:TRUE;
- else
- *ret = !strcmpW(V_BSTR(lval), V_BSTR(rval));
+ case JSV_NUMBER:
+ *ret = get_number(lval) == get_number(rval);
break;
- case VT_DISPATCH:
- return disp_cmp(V_DISPATCH(lval), V_DISPATCH(rval), ret);
- case VT_BOOL:
- *ret = !V_BOOL(lval) == !V_BOOL(rval);
+ case JSV_BOOL:
+ *ret = !get_bool(lval) == !get_bool(rval);
break;
- default:
- FIXME("unimplemented vt %d\n", V_VT(lval));
+ case JSV_VARIANT:
+ FIXME("VARIANT not implemented\n");
return E_NOTIMPL;
}
return S_OK;
}
-static HRESULT literal_to_var(script_ctx_t *ctx, literal_t *literal, VARIANT *v)
-{
- switch(literal->type) {
- case LT_NULL:
- V_VT(v) = VT_NULL;
- break;
- case LT_INT:
- V_VT(v) = VT_I4;
- V_I4(v) = literal->u.lval;
- break;
- case LT_DOUBLE:
- V_VT(v) = VT_R8;
- V_R8(v) = literal->u.dval;
- break;
- case LT_STRING: {
- BSTR str = SysAllocString(literal->u.wstr);
- if(!str)
- return E_OUTOFMEMORY;
-
- V_VT(v) = VT_BSTR;
- V_BSTR(v) = str;
- break;
- }
- case LT_BOOL:
- V_VT(v) = VT_BOOL;
- V_BOOL(v) = literal->u.bval;
- break;
- case LT_REGEXP: {
- DispatchEx *regexp;
- HRESULT hres;
-
- hres = create_regexp(ctx, literal->u.regexp.str, literal->u.regexp.str_len,
- literal->u.regexp.flags, ®exp);
- if(FAILED(hres))
- return hres;
-
- V_VT(v) = VT_DISPATCH;
- V_DISPATCH(v) = (IDispatch*)_IDispatchEx_(regexp);
- }
- }
-
- return S_OK;
-}
-
static BOOL lookup_global_members(script_ctx_t *ctx, BSTR identifier, exprval_t *ret)
{
named_item_t *item;
for(item = ctx->named_items; item; item = item->next) {
if(item->flags & SCRIPTITEM_GLOBALMEMBERS) {
- hres = disp_get_id(ctx, item->disp, identifier, 0, &id);
+ hres = disp_get_id(ctx, item->disp, identifier, identifier, 0, &id);
if(SUCCEEDED(hres)) {
if(ret)
exprval_set_idref(ret, item->disp, id);
return FALSE;
}
-HRESULT exec_source(exec_ctx_t *ctx, parser_ctx_t *parser, source_elements_t *source, exec_type_t exec_type,
- jsexcept_t *ei, VARIANT *retv)
-{
- script_ctx_t *script = parser->script;
- function_declaration_t *func;
- parser_ctx_t *prev_parser;
- var_list_t *var;
- VARIANT val, tmp;
- statement_t *stat;
- exec_ctx_t *prev_ctx;
- return_type_t rt;
- HRESULT hres = S_OK;
-
- for(func = source->functions; func; func = func->next) {
- DispatchEx *func_obj;
- VARIANT var;
-
- hres = create_source_function(parser, func->expr->parameter_list, func->expr->source_elements,
- ctx->scope_chain, func->expr->src_str, func->expr->src_len, &func_obj);
- if(FAILED(hres))
- return hres;
-
- V_VT(&var) = VT_DISPATCH;
- V_DISPATCH(&var) = (IDispatch*)_IDispatchEx_(func_obj);
- hres = jsdisp_propput_name(ctx->var_disp, func->expr->identifier, &var, ei, NULL);
- jsdisp_release(func_obj);
- if(FAILED(hres))
- return hres;
- }
-
- for(var = source->variables; var; var = var->next) {
- DISPID id = 0;
- BSTR name;
-
- name = SysAllocString(var->identifier);
- if(!name)
- return E_OUTOFMEMORY;
-
- if(!lookup_global_members(parser->script, name, NULL))
- hres = jsdisp_get_id(ctx->var_disp, var->identifier, fdexNameEnsure, &id);
- SysFreeString(name);
- if(FAILED(hres))
- return hres;
- }
-
- prev_ctx = script->exec_ctx;
- script->exec_ctx = ctx;
-
- prev_parser = ctx->parser;
- ctx->parser = parser;
-
- V_VT(&val) = VT_EMPTY;
- memset(&rt, 0, sizeof(rt));
- rt.type = RT_NORMAL;
-
- for(stat = source->statement; stat; stat = stat->next) {
- hres = stat_eval(ctx, stat, &rt, &tmp);
- if(FAILED(hres))
- break;
-
- VariantClear(&val);
- val = tmp;
- if(rt.type != RT_NORMAL)
- break;
- }
-
- script->exec_ctx = prev_ctx;
- ctx->parser = prev_parser;
-
- if(rt.type != RT_NORMAL && rt.type != RT_RETURN) {
- FIXME("wrong rt %d\n", rt.type);
- hres = E_FAIL;
- }
-
- *ei = rt.ei;
- if(FAILED(hres)) {
- VariantClear(&val);
- return hres;
- }
-
- if(retv && (exec_type == EXECT_EVAL || rt.type == RT_RETURN))
- *retv = val;
- else {
- if (retv) {
- VariantInit(retv);
- }
- VariantClear(&val);
- }
- return S_OK;
-}
-
/* ECMA-262 3rd Edition 10.1.4 */
-static HRESULT identifier_eval(exec_ctx_t *ctx, BSTR identifier, DWORD flags, jsexcept_t *ei, exprval_t *ret)
+static HRESULT identifier_eval(script_ctx_t *ctx, BSTR identifier, exprval_t *ret)
{
scope_chain_t *scope;
named_item_t *item;
TRACE("%s\n", debugstr_w(identifier));
- for(scope = ctx->scope_chain; scope; scope = scope->next) {
- hres = jsdisp_get_id(scope->obj, identifier, 0, &id);
- if(SUCCEEDED(hres))
- break;
- }
-
- if(scope) {
- exprval_set_idref(ret, (IDispatch*)_IDispatchEx_(scope->obj), id);
- return S_OK;
+ for(scope = ctx->exec_ctx->scope_chain; scope; scope = scope->next) {
+ if(scope->jsobj)
+ hres = jsdisp_get_id(scope->jsobj, identifier, fdexNameImplicit, &id);
+ else
+ hres = disp_get_id(ctx, scope->obj, identifier, identifier, fdexNameImplicit, &id);
+ if(SUCCEEDED(hres)) {
+ exprval_set_idref(ret, scope->obj, id);
+ return S_OK;
+ }
}
- hres = jsdisp_get_id(ctx->parser->script->global, identifier, 0, &id);
+ hres = jsdisp_get_id(ctx->global, identifier, 0, &id);
if(SUCCEEDED(hres)) {
- exprval_set_idref(ret, (IDispatch*)_IDispatchEx_(ctx->parser->script->global), id);
+ exprval_set_idref(ret, to_disp(ctx->global), id);
return S_OK;
}
- for(item = ctx->parser->script->named_items; item; item = item->next) {
+ for(item = ctx->named_items; item; item = item->next) {
if((item->flags & SCRIPTITEM_ISVISIBLE) && !strcmpW(item->name, identifier)) {
if(!item->disp) {
IUnknown *unk;
- if(!ctx->parser->script->site)
+ if(!ctx->site)
break;
- hres = IActiveScriptSite_GetItemInfo(ctx->parser->script->site, identifier,
+ hres = IActiveScriptSite_GetItemInfo(ctx->site, identifier,
SCRIPTINFO_IUNKNOWN, &unk, NULL);
if(FAILED(hres)) {
WARN("GetItemInfo failed: %08x\n", hres);
}
}
- ret->type = EXPRVAL_VARIANT;
- V_VT(&ret->u.var) = VT_DISPATCH;
- V_DISPATCH(&ret->u.var) = item->disp;
IDispatch_AddRef(item->disp);
+ ret->type = EXPRVAL_JSVAL;
+ ret->u.val = jsval_disp(item->disp);
return S_OK;
}
}
- if(lookup_global_members(ctx->parser->script, identifier, ret))
+ if(lookup_global_members(ctx, identifier, ret))
return S_OK;
- if(flags & EXPR_NEWREF) {
- hres = jsdisp_get_id(ctx->parser->script->global, identifier, fdexNameEnsure, &id);
- if(FAILED(hres))
- return hres;
+ ret->type = EXPRVAL_INVALID;
+ return S_OK;
+}
- exprval_set_idref(ret, (IDispatch*)_IDispatchEx_(ctx->parser->script->global), id);
- return S_OK;
- }
+static inline BSTR get_op_bstr(exec_ctx_t *ctx, int i){
+ return ctx->code->instrs[ctx->ip].u.arg[i].bstr;
+}
- ret->type = EXPRVAL_INVALID;
- ret->u.identifier = SysAllocString(identifier);
- if(!ret->u.identifier)
- return E_OUTOFMEMORY;
+static inline unsigned get_op_uint(exec_ctx_t *ctx, int i){
+ return ctx->code->instrs[ctx->ip].u.arg[i].uint;
+}
- return S_OK;
+static inline unsigned get_op_int(exec_ctx_t *ctx, int i){
+ return ctx->code->instrs[ctx->ip].u.arg[i].lng;
+}
+
+static inline jsstr_t *get_op_str(exec_ctx_t *ctx, int i){
+ return ctx->code->instrs[ctx->ip].u.arg[i].str;
+}
+
+static inline double get_op_double(exec_ctx_t *ctx){
+ return ctx->code->instrs[ctx->ip].u.dbl;
}
-/* ECMA-262 3rd Edition 12.1 */
-HRESULT block_statement_eval(exec_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
+/* ECMA-262 3rd Edition 12.2 */
+static HRESULT interp_var_set(exec_ctx_t *ctx)
{
- block_statement_t *stat = (block_statement_t*)_stat;
- VARIANT val, tmp;
- statement_t *iter;
- HRESULT hres = S_OK;
+ const BSTR name = get_op_bstr(ctx, 0);
+ jsval_t val;
+ HRESULT hres;
- TRACE("\n");
+ TRACE("%s\n", debugstr_w(name));
- V_VT(&val) = VT_EMPTY;
- for(iter = stat->stat_list; iter; iter = iter->next) {
- hres = stat_eval(ctx, iter, rt, &tmp);
- if(FAILED(hres))
- break;
+ val = stack_pop(ctx);
+ hres = jsdisp_propput_name(ctx->var_disp, name, val);
+ jsval_release(val);
+ return hres;
+}
- VariantClear(&val);
- val = tmp;
- if(rt->type != RT_NORMAL)
- break;
- }
+/* ECMA-262 3rd Edition 12.6.4 */
+static HRESULT interp_forin(exec_ctx_t *ctx)
+{
+ const HRESULT arg = get_op_uint(ctx, 0);
+ IDispatch *var_obj, *obj = NULL;
+ IDispatchEx *dispex;
+ DISPID id, var_id;
+ BSTR name = NULL;
+ HRESULT hres;
- if(FAILED(hres)) {
- VariantClear(&val);
- return hres;
+ TRACE("\n");
+
+ assert(is_number(stack_top(ctx)));
+ id = get_number(stack_top(ctx));
+
+ var_obj = stack_topn_objid(ctx, 1, &var_id);
+ if(!var_obj) {
+ FIXME("invalid ref\n");
+ return E_FAIL;
}
- *ret = val;
- return S_OK;
-}
+ if(is_object_instance(stack_topn(ctx, 3)))
+ obj = get_object(stack_topn(ctx, 3));
-/* ECMA-262 3rd Edition 12.2 */
-static HRESULT variable_list_eval(exec_ctx_t *ctx, variable_declaration_t *var_list, jsexcept_t *ei)
-{
- variable_declaration_t *iter;
- HRESULT hres = S_OK;
+ if(obj) {
+ hres = IDispatch_QueryInterface(obj, &IID_IDispatchEx, (void**)&dispex);
+ if(SUCCEEDED(hres)) {
+ hres = IDispatchEx_GetNextDispID(dispex, fdexEnumDefault, id, &id);
+ if(hres == S_OK)
+ hres = IDispatchEx_GetMemberName(dispex, id, &name);
+ IDispatchEx_Release(dispex);
+ if(FAILED(hres))
+ return hres;
+ }else {
+ TRACE("No IDispatchEx\n");
+ }
+ }
- for(iter = var_list; iter; iter = iter->next) {
- exprval_t exprval;
- VARIANT val;
+ if(name) {
+ jsstr_t *str;
- if(!iter->expr)
- continue;
+ str = jsstr_alloc_len(name, SysStringLen(name));
+ SysFreeString(name);
+ if(!str)
+ return E_OUTOFMEMORY;
- hres = expr_eval(ctx, iter->expr, 0, ei, &exprval);
- if(FAILED(hres))
- break;
+ stack_pop(ctx);
+ stack_push(ctx, jsval_number(id)); /* safe, just after pop() */
- hres = exprval_to_value(ctx->parser->script, &exprval, ei, &val);
- exprval_release(&exprval);
+ hres = disp_propput(ctx->script, var_obj, var_id, jsval_string(str));
+ jsstr_release(str);
if(FAILED(hres))
- break;
+ return hres;
- hres = jsdisp_propput_name(ctx->var_disp, iter->identifier, &val, ei, NULL/*FIXME*/);
- VariantClear(&val);
- if(FAILED(hres))
- break;
+ ctx->ip++;
+ }else {
+ stack_popn(ctx, 4);
+ ctx->ip = arg;
}
-
- return hres;
+ return S_OK;
}
-/* ECMA-262 3rd Edition 12.2 */
-HRESULT var_statement_eval(exec_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
+/* ECMA-262 3rd Edition 12.10 */
+static HRESULT interp_push_scope(exec_ctx_t *ctx)
{
- var_statement_t *stat = (var_statement_t*)_stat;
+ IDispatch *disp;
+ jsval_t v;
HRESULT hres;
TRACE("\n");
- hres = variable_list_eval(ctx, stat->variable_list, &rt->ei);
+ v = stack_pop(ctx);
+ hres = to_object(ctx->script, v, &disp);
+ jsval_release(v);
if(FAILED(hres))
return hres;
- V_VT(ret) = VT_EMPTY;
- return S_OK;
+ hres = scope_push(ctx->scope_chain, to_jsdisp(disp), disp, &ctx->scope_chain);
+ IDispatch_Release(disp);
+ return hres;
}
-/* ECMA-262 3rd Edition 12.3 */
-HRESULT empty_statement_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
+/* ECMA-262 3rd Edition 12.10 */
+static HRESULT interp_pop_scope(exec_ctx_t *ctx)
{
TRACE("\n");
- V_VT(ret) = VT_EMPTY;
+ scope_pop(&ctx->scope_chain);
return S_OK;
}
-/* ECMA-262 3rd Edition 12.4 */
-HRESULT expression_statement_eval(exec_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
+/* ECMA-262 3rd Edition 12.13 */
+static HRESULT interp_case(exec_ctx_t *ctx)
{
- expression_statement_t *stat = (expression_statement_t*)_stat;
- exprval_t exprval;
- VARIANT val;
+ const unsigned arg = get_op_uint(ctx, 0);
+ jsval_t v;
+ BOOL b;
HRESULT hres;
TRACE("\n");
- hres = expr_eval(ctx, stat->expr, EXPR_NOVAL, &rt->ei, &exprval);
- if(FAILED(hres))
- return hres;
-
- hres = exprval_to_value(ctx->parser->script, &exprval, &rt->ei, &val);
- exprval_release(&exprval);
+ v = stack_pop(ctx);
+ hres = equal2_values(stack_top(ctx), v, &b);
+ jsval_release(v);
if(FAILED(hres))
return hres;
- *ret = val;
- TRACE("= %s\n", debugstr_variant(ret));
+ if(b) {
+ stack_popn(ctx, 1);
+ ctx->ip = arg;
+ }else {
+ ctx->ip++;
+ }
return S_OK;
}
-/* ECMA-262 3rd Edition 12.5 */
-HRESULT if_statement_eval(exec_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
+/* ECMA-262 3rd Edition 12.13 */
+static HRESULT interp_throw(exec_ctx_t *ctx)
{
- if_statement_t *stat = (if_statement_t*)_stat;
- exprval_t exprval;
- VARIANT_BOOL b;
- HRESULT hres;
-
TRACE("\n");
- hres = expr_eval(ctx, stat->expr, 0, &rt->ei, &exprval);
- if(FAILED(hres))
- return hres;
-
- hres = exprval_to_boolean(ctx->parser->script, &exprval, &rt->ei, &b);
- exprval_release(&exprval);
- if(FAILED(hres))
- return hres;
-
- if(b)
- hres = stat_eval(ctx, stat->if_stat, rt, ret);
- else if(stat->else_stat)
- hres = stat_eval(ctx, stat->else_stat, rt, ret);
- else
- V_VT(ret) = VT_EMPTY;
-
- return hres;
+ jsval_release(ctx->script->ei.val);
+ ctx->script->ei.val = stack_pop(ctx);
+ return DISP_E_EXCEPTION;
}
-/* ECMA-262 3rd Edition 12.6.2 */
-HRESULT while_statement_eval(exec_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
+static HRESULT interp_throw_ref(exec_ctx_t *ctx)
{
- while_statement_t *stat = (while_statement_t*)_stat;
- exprval_t exprval;
- VARIANT val, tmp;
- VARIANT_BOOL b;
- BOOL test_expr;
- HRESULT hres;
-
- TRACE("\n");
-
- V_VT(&val) = VT_EMPTY;
- test_expr = !stat->do_while;
-
- while(1) {
- if(test_expr) {
- hres = expr_eval(ctx, stat->expr, 0, &rt->ei, &exprval);
- if(FAILED(hres))
- break;
-
- hres = exprval_to_boolean(ctx->parser->script, &exprval, &rt->ei, &b);
- exprval_release(&exprval);
- if(FAILED(hres) || !b)
- break;
- }else {
- test_expr = TRUE;
- }
-
- hres = stat_eval(ctx, stat->statement, rt, &tmp);
- if(FAILED(hres))
- break;
+ const HRESULT arg = get_op_uint(ctx, 0);
- VariantClear(&val);
- val = tmp;
+ TRACE("%08x\n", arg);
- if(rt->type == RT_CONTINUE)
- rt->type = RT_NORMAL;
- if(rt->type != RT_NORMAL)
- break;
- }
-
- if(FAILED(hres)) {
- VariantClear(&val);
- return hres;
- }
-
- if(rt->type == RT_BREAK)
- rt->type = RT_NORMAL;
-
- *ret = val;
- return S_OK;
+ return throw_reference_error(ctx->script, arg, NULL);
}
-/* ECMA-262 3rd Edition 12.6.3 */
-HRESULT for_statement_eval(exec_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
+static HRESULT interp_throw_type(exec_ctx_t *ctx)
{
- for_statement_t *stat = (for_statement_t*)_stat;
- VARIANT val, tmp, retv;
- exprval_t exprval;
- VARIANT_BOOL b;
- HRESULT hres;
-
- TRACE("\n");
-
- if(stat->variable_list) {
- hres = variable_list_eval(ctx, stat->variable_list, &rt->ei);
- if(FAILED(hres))
- return hres;
- }else if(stat->begin_expr) {
- hres = expr_eval(ctx, stat->begin_expr, EXPR_NEWREF, &rt->ei, &exprval);
- if(FAILED(hres))
- return hres;
-
- hres = exprval_to_value(ctx->parser->script, &exprval, &rt->ei, &val);
- exprval_release(&exprval);
- if(FAILED(hres))
- return hres;
-
- VariantClear(&val);
- }
+ const HRESULT hres = get_op_uint(ctx, 0);
+ jsstr_t *str = get_op_str(ctx, 1);
- V_VT(&retv) = VT_EMPTY;
+ TRACE("%08x %s\n", hres, debugstr_jsstr(str));
- while(1) {
- if(stat->expr) {
- hres = expr_eval(ctx, stat->expr, 0, &rt->ei, &exprval);
- if(FAILED(hres))
- break;
-
- hres = exprval_to_boolean(ctx->parser->script, &exprval, &rt->ei, &b);
- exprval_release(&exprval);
- if(FAILED(hres) || !b)
- break;
- }
-
- hres = stat_eval(ctx, stat->statement, rt, &tmp);
- if(FAILED(hres))
- break;
-
- VariantClear(&retv);
- retv = tmp;
-
- if(rt->type == RT_CONTINUE)
- rt->type = RT_NORMAL;
- else if(rt->type != RT_NORMAL)
- break;
-
- if(stat->end_expr) {
- hres = expr_eval(ctx, stat->end_expr, 0, &rt->ei, &exprval);
- if(FAILED(hres))
- break;
-
- hres = exprval_to_value(ctx->parser->script, &exprval, &rt->ei, &val);
- exprval_release(&exprval);
- if(FAILED(hres))
- break;
-
- VariantClear(&val);
- }
- }
-
- if(FAILED(hres)) {
- VariantClear(&retv);
- return hres;
- }
-
- if(rt->type == RT_BREAK)
- rt->type = RT_NORMAL;
-
- *ret = retv;
- return S_OK;
+ return throw_type_error(ctx->script, hres, str->str);
}
-/* ECMA-262 3rd Edition 12.6.4 */
-HRESULT forin_statement_eval(exec_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
+/* ECMA-262 3rd Edition 12.14 */
+static HRESULT interp_push_except(exec_ctx_t *ctx)
{
- forin_statement_t *stat = (forin_statement_t*)_stat;
- VARIANT val, name, retv, tmp;
- DISPID id = DISPID_STARTENUM;
- BSTR str, identifier = NULL;
- IDispatchEx *in_obj;
- exprval_t exprval;
- HRESULT hres;
+ const unsigned arg1 = get_op_uint(ctx, 0);
+ const BSTR arg2 = get_op_bstr(ctx, 1);
+ except_frame_t *except;
+ unsigned stack_top;
TRACE("\n");
- if(stat->variable) {
- hres = variable_list_eval(ctx, stat->variable, &rt->ei);
- if(FAILED(hres))
- return hres;
- }
-
- hres = expr_eval(ctx, stat->in_expr, EXPR_NEWREF, &rt->ei, &exprval);
- if(FAILED(hres))
- return hres;
-
- hres = exprval_to_value(ctx->parser->script, &exprval, &rt->ei, &val);
- exprval_release(&exprval);
- if(FAILED(hres))
- return hres;
-
- if(V_VT(&val) != VT_DISPATCH) {
- TRACE("in vt %d\n", V_VT(&val));
- VariantClear(&val);
- V_VT(ret) = VT_EMPTY;
- return S_OK;
- }
-
- hres = IDispatch_QueryInterface(V_DISPATCH(&val), &IID_IDispatchEx, (void**)&in_obj);
- IDispatch_Release(V_DISPATCH(&val));
- if(FAILED(hres)) {
- FIXME("Object doesn't support IDispatchEx\n");
- return E_NOTIMPL;
- }
-
- V_VT(&retv) = VT_EMPTY;
+ stack_top = ctx->top;
- if(stat->variable)
- identifier = SysAllocString(stat->variable->identifier);
-
- while(1) {
- hres = IDispatchEx_GetNextDispID(in_obj, fdexEnumDefault, id, &id);
- if(FAILED(hres) || hres == S_FALSE)
- break;
+ if(!arg2) {
+ HRESULT hres;
- hres = IDispatchEx_GetMemberName(in_obj, id, &str);
+ hres = stack_push(ctx, jsval_bool(TRUE));
if(FAILED(hres))
- break;
-
- TRACE("iter %s\n", debugstr_w(str));
-
- if(stat->variable)
- hres = identifier_eval(ctx, identifier, 0, NULL, &exprval);
- else
- hres = expr_eval(ctx, stat->expr, EXPR_NEWREF, &rt->ei, &exprval);
- if(SUCCEEDED(hres)) {
- V_VT(&name) = VT_BSTR;
- V_BSTR(&name) = str;
- hres = put_value(ctx->parser->script, &exprval, &name, &rt->ei);
- exprval_release(&exprval);
- }
- SysFreeString(str);
- if(FAILED(hres))
- break;
-
- hres = stat_eval(ctx, stat->statement, rt, &tmp);
+ return hres;
+ hres = stack_push(ctx, jsval_bool(TRUE));
if(FAILED(hres))
- break;
-
- VariantClear(&retv);
- retv = tmp;
-
- if(rt->type == RT_CONTINUE)
- rt->type = RT_NORMAL;
- else if(rt->type != RT_NORMAL)
- break;
- }
-
- SysFreeString(identifier);
- IDispatchEx_Release(in_obj);
- if(FAILED(hres)) {
- VariantClear(&retv);
- return hres;
+ return hres;
}
- if(rt->type == RT_BREAK)
- rt->type = RT_NORMAL;
-
- *ret = retv;
- return S_OK;
-}
-
-/* ECMA-262 3rd Edition 12.7 */
-HRESULT continue_statement_eval(exec_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
-{
- branch_statement_t *stat = (branch_statement_t*)_stat;
-
- TRACE("\n");
-
- if(stat->identifier) {
- FIXME("indentifier not implemented\n");
- return E_NOTIMPL;
- }
+ except = heap_alloc(sizeof(*except));
+ if(!except)
+ return E_OUTOFMEMORY;
- rt->type = RT_CONTINUE;
- V_VT(ret) = VT_EMPTY;
+ except->stack_top = stack_top;
+ except->scope = ctx->scope_chain;
+ except->catch_off = arg1;
+ except->ident = arg2;
+ except->next = ctx->except_frame;
+ ctx->except_frame = except;
return S_OK;
}
-/* ECMA-262 3rd Edition 12.8 */
-HRESULT break_statement_eval(exec_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
+/* ECMA-262 3rd Edition 12.14 */
+static HRESULT interp_pop_except(exec_ctx_t *ctx)
{
- branch_statement_t *stat = (branch_statement_t*)_stat;
+ except_frame_t *except;
TRACE("\n");
- if(stat->identifier) {
- FIXME("indentifier not implemented\n");
- return E_NOTIMPL;
- }
+ except = ctx->except_frame;
+ assert(except != NULL);
- rt->type = RT_BREAK;
- V_VT(ret) = VT_EMPTY;
+ ctx->except_frame = except->next;
+ heap_free(except);
return S_OK;
}
-/* ECMA-262 3rd Edition 12.9 */
-HRESULT return_statement_eval(exec_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
+/* ECMA-262 3rd Edition 12.14 */
+static HRESULT interp_end_finally(exec_ctx_t *ctx)
{
- expression_statement_t *stat = (expression_statement_t*)_stat;
- HRESULT hres;
+ //jsval_t v;
TRACE("\n");
- if(stat->expr) {
- exprval_t exprval;
+ assert(is_bool(stack_top(ctx)));
+ if(!get_bool(stack_top(ctx))) {
+ TRACE("passing exception\n");
- hres = expr_eval(ctx, stat->expr, 0, &rt->ei, &exprval);
- if(FAILED(hres))
- return hres;
+ //jsval_release(v);
+ stack_popn(ctx, 1);
- hres = exprval_to_value(ctx->parser->script, &exprval, &rt->ei, ret);
- exprval_release(&exprval);
- if(FAILED(hres))
- return hres;
- }else {
- V_VT(ret) = VT_EMPTY;
+ ctx->script->ei.val = stack_pop(ctx);
+ return DISP_E_EXCEPTION;
}
- TRACE("= %s\n", debugstr_variant(ret));
- rt->type = RT_RETURN;
+ stack_popn(ctx, 2);
return S_OK;
}
-/* ECMA-262 3rd Edition 12.10 */
-HRESULT with_statement_eval(exec_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
+/* ECMA-262 3rd Edition 13 */
+static HRESULT interp_func(exec_ctx_t *ctx)
{
- with_statement_t *stat = (with_statement_t*)_stat;
- exprval_t exprval;
- IDispatch *disp;
- DispatchEx *obj;
- VARIANT val;
+ unsigned func_idx = get_op_uint(ctx, 0);
+ jsdisp_t *dispex;
HRESULT hres;
- TRACE("\n");
-
- hres = expr_eval(ctx, stat->expr, 0, &rt->ei, &exprval);
- if(FAILED(hres))
- return hres;
-
- hres = exprval_to_value(ctx->parser->script, &exprval, &rt->ei, &val);
- exprval_release(&exprval);
- if(FAILED(hres))
- return hres;
-
- hres = to_object(ctx->parser->script, &val, &disp);
- VariantClear(&val);
- if(FAILED(hres))
- return hres;
-
- obj = iface_to_jsdisp((IUnknown*)disp);
- IDispatch_Release(disp);
- if(!obj) {
- FIXME("disp id not jsdisp\n");
- return E_NOTIMPL;
- }
+ TRACE("%d\n", func_idx);
- hres = scope_push(ctx->scope_chain, obj, &ctx->scope_chain);
- jsdisp_release(obj);
+ hres = create_source_function(ctx->script, ctx->code, ctx->func_code->funcs+func_idx,
+ ctx->scope_chain, &dispex);
if(FAILED(hres))
return hres;
- hres = stat_eval(ctx, stat->statement, rt, ret);
-
- scope_pop(&ctx->scope_chain);
- return hres;
-}
-
-/* ECMA-262 3rd Edition 12.12 */
-HRESULT labelled_statement_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
-{
- FIXME("\n");
- return E_NOTIMPL;
+ return stack_push(ctx, jsval_obj(dispex));
}
-/* ECMA-262 3rd Edition 12.13 */
-HRESULT switch_statement_eval(exec_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
+/* ECMA-262 3rd Edition 11.2.1 */
+static HRESULT interp_array(exec_ctx_t *ctx)
{
- switch_statement_t *stat = (switch_statement_t*)_stat;
- case_clausule_t *iter, *default_clausule = NULL;
- statement_t *stat_iter;
- VARIANT val, cval;
- exprval_t exprval;
- BOOL b;
+ jsval_t v, namev;
+ IDispatch *obj;
+ jsstr_t *name;
+ DISPID id;
HRESULT hres;
TRACE("\n");
- hres = expr_eval(ctx, stat->expr, 0, &rt->ei, &exprval);
- if(FAILED(hres))
- return hres;
-
- hres = exprval_to_value(ctx->parser->script, &exprval, &rt->ei, &val);
- exprval_release(&exprval);
- if(FAILED(hres))
- return hres;
-
- for(iter = stat->case_list; iter; iter = iter->next) {
- if(!iter->expr) {
- default_clausule = iter;
- continue;
- }
+ namev = stack_pop(ctx);
- hres = expr_eval(ctx, iter->expr, 0, &rt->ei, &exprval);
- if(FAILED(hres))
- break;
-
- hres = exprval_to_value(ctx->parser->script, &exprval, &rt->ei, &cval);
- exprval_release(&exprval);
- if(FAILED(hres))
- break;
-
- hres = equal2_values(&val, &cval, &b);
- VariantClear(&cval);
- if(FAILED(hres) || b)
- break;
- }
-
- VariantClear(&val);
- if(FAILED(hres))
+ hres = stack_pop_object(ctx, &obj);
+ if(FAILED(hres)) {
+ jsval_release(namev);
return hres;
-
- if(!iter)
- iter = default_clausule;
-
- V_VT(&val) = VT_EMPTY;
- if(iter) {
- VARIANT tmp;
-
- for(stat_iter = iter->stat; stat_iter; stat_iter = stat_iter->next) {
- hres = stat_eval(ctx, stat_iter, rt, &tmp);
- if(FAILED(hres))
- break;
-
- VariantClear(&val);
- val = tmp;
-
- if(rt->type != RT_NORMAL)
- break;
- }
}
+ hres = to_string(ctx->script, namev, &name);
+ jsval_release(namev);
if(FAILED(hres)) {
- VariantClear(&val);
+ IDispatch_Release(obj);
return hres;
}
- if(rt->type == RT_BREAK)
- rt->type = RT_NORMAL;
+ hres = disp_get_id(ctx->script, obj, name->str, NULL, 0, &id);
+ jsstr_release(name);
+ if(SUCCEEDED(hres)) {
+ hres = disp_propget(ctx->script, obj, id, &v);
+ }else if(hres == DISP_E_UNKNOWNNAME) {
+ v = jsval_undefined();
+ hres = S_OK;
+ }
+ IDispatch_Release(obj);
+ if(FAILED(hres))
+ return hres;
- *ret = val;
- return S_OK;
+ return stack_push(ctx, v);
}
-/* ECMA-262 3rd Edition 12.13 */
-HRESULT throw_statement_eval(exec_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
+/* ECMA-262 3rd Edition 11.2.1 */
+static HRESULT interp_member(exec_ctx_t *ctx)
{
- expression_statement_t *stat = (expression_statement_t*)_stat;
- exprval_t exprval;
- VARIANT val;
+ const BSTR arg = get_op_bstr(ctx, 0);
+ IDispatch *obj;
+ jsval_t v;
+ DISPID id;
HRESULT hres;
TRACE("\n");
- hres = expr_eval(ctx, stat->expr, 0, &rt->ei, &exprval);
+ hres = stack_pop_object(ctx, &obj);
if(FAILED(hres))
return hres;
- hres = exprval_to_value(ctx->parser->script, &exprval, &rt->ei, &val);
- exprval_release(&exprval);
- if(FAILED(hres))
- return hres;
-
- rt->ei.var = val;
- return DISP_E_EXCEPTION;
-}
-
-/* ECMA-262 3rd Edition 12.14 */
-static HRESULT catch_eval(exec_ctx_t *ctx, catch_block_t *block, return_type_t *rt, VARIANT *ret)
-{
- DispatchEx *var_disp;
- VARIANT ex, val;
- HRESULT hres;
-
- ex = rt->ei.var;
- memset(&rt->ei, 0, sizeof(jsexcept_t));
-
- hres = create_dispex(ctx->parser->script, NULL, NULL, &var_disp);
+ hres = disp_get_id(ctx->script, obj, arg, arg, 0, &id);
if(SUCCEEDED(hres)) {
- hres = jsdisp_propput_name(var_disp, block->identifier, &ex, &rt->ei, NULL/*FIXME*/);
- if(SUCCEEDED(hres)) {
- hres = scope_push(ctx->scope_chain, var_disp, &ctx->scope_chain);
- if(SUCCEEDED(hres)) {
- hres = stat_eval(ctx, block->statement, rt, &val);
- scope_pop(&ctx->scope_chain);
- }
- }
-
- jsdisp_release(var_disp);
+ hres = disp_propget(ctx->script, obj, id, &v);
+ }else if(hres == DISP_E_UNKNOWNNAME) {
+ v = jsval_undefined();
+ hres = S_OK;
}
-
- VariantClear(&ex);
+ IDispatch_Release(obj);
if(FAILED(hres))
return hres;
- *ret = val;
- return S_OK;
+ return stack_push(ctx, v);
}
-/* ECMA-262 3rd Edition 12.14 */
-HRESULT try_statement_eval(exec_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
+/* ECMA-262 3rd Edition 11.2.1 */
+static HRESULT interp_memberid(exec_ctx_t *ctx)
{
- try_statement_t *stat = (try_statement_t*)_stat;
- VARIANT val;
+ const unsigned arg = get_op_uint(ctx, 0);
+ jsval_t objv, namev;
+ IDispatch *obj;
+ jsstr_t *name;
+ DISPID id;
HRESULT hres;
- TRACE("\n");
-
- hres = stat_eval(ctx, stat->try_statement, rt, &val);
- if(FAILED(hres)) {
- TRACE("EXCEPTION\n");
- if(!stat->catch_block)
- return hres;
+ TRACE("%x\n", arg);
- hres = catch_eval(ctx, stat->catch_block, rt, &val);
- if(FAILED(hres))
- return hres;
- }
+ namev = stack_pop(ctx);
+ objv = stack_pop(ctx);
- if(stat->finally_statement) {
- VariantClear(&val);
- hres = stat_eval(ctx, stat->finally_statement, rt, &val);
+ hres = to_object(ctx->script, objv, &obj);
+ jsval_release(objv);
+ if(SUCCEEDED(hres)) {
+ hres = to_string(ctx->script, namev, &name);
if(FAILED(hres))
- return hres;
+ IDispatch_Release(obj);
}
-
- *ret = val;
- return S_OK;
-}
-
-static HRESULT return_bool(exprval_t *ret, DWORD b)
-{
- ret->type = EXPRVAL_VARIANT;
- V_VT(&ret->u.var) = VT_BOOL;
- V_BOOL(&ret->u.var) = b ? VARIANT_TRUE : VARIANT_FALSE;
-
- return S_OK;
-}
-
-static HRESULT get_binary_expr_values(exec_ctx_t *ctx, binary_expression_t *expr, jsexcept_t *ei, VARIANT *lval, VARIANT *rval)
-{
- exprval_t exprval;
- HRESULT hres;
-
- hres = expr_eval(ctx, expr->expression1, 0, ei, &exprval);
+ jsval_release(namev);
if(FAILED(hres))
return hres;
- hres = exprval_to_value(ctx->parser->script, &exprval, ei, lval);
- exprval_release(&exprval);
- if(FAILED(hres))
- return hres;
-
- hres = expr_eval(ctx, expr->expression2, 0, ei, &exprval);
- if(SUCCEEDED(hres)) {
- hres = exprval_to_value(ctx->parser->script, &exprval, ei, rval);
- exprval_release(&exprval);
- }
-
+ hres = disp_get_id(ctx->script, obj, name->str, NULL, arg, &id);
+ jsstr_release(name);
if(FAILED(hres)) {
- VariantClear(lval);
- return hres;
+ IDispatch_Release(obj);
+ if(hres == DISP_E_UNKNOWNNAME && !(arg & fdexNameEnsure)) {
+ obj = NULL;
+ id = JS_E_INVALID_PROPERTY;
+ }else {
+ ERR("failed %08x\n", hres);
+ return hres;
+ }
}
- return S_OK;
-}
-
-typedef HRESULT (*oper_t)(exec_ctx_t*,VARIANT*,VARIANT*,jsexcept_t*,VARIANT*);
-
-static HRESULT binary_expr_eval(exec_ctx_t *ctx, binary_expression_t *expr, oper_t oper, jsexcept_t *ei,
- exprval_t *ret)
-{
- VARIANT lval, rval, retv;
- HRESULT hres;
-
- hres = get_binary_expr_values(ctx, expr, ei, &lval, &rval);
- if(FAILED(hres))
- return hres;
-
- hres = oper(ctx, &lval, &rval, ei, &retv);
- VariantClear(&lval);
- VariantClear(&rval);
- if(FAILED(hres))
- return hres;
-
- ret->type = EXPRVAL_VARIANT;
- ret->u.var = retv;
- return S_OK;
+ return stack_push_objid(ctx, obj, id);
}
-/* ECMA-262 3rd Edition 11.13.2 */
-static HRESULT assign_oper_eval(exec_ctx_t *ctx, expression_t *lexpr, expression_t *rexpr, oper_t oper,
- jsexcept_t *ei, exprval_t *ret)
+/* ECMA-262 3rd Edition 11.2.1 */
+static HRESULT interp_refval(exec_ctx_t *ctx)
{
- VARIANT retv, lval, rval;
- exprval_t exprval, exprvalr;
+ IDispatch *disp;
+ jsval_t v;
+ DISPID id;
HRESULT hres;
- hres = expr_eval(ctx, lexpr, EXPR_NEWREF, ei, &exprval);
- if(FAILED(hres))
- return hres;
-
- hres = exprval_value(ctx->parser->script, &exprval, ei, &lval);
- if(SUCCEEDED(hres)) {
- hres = expr_eval(ctx, rexpr, 0, ei, &exprvalr);
- if(SUCCEEDED(hres)) {
- hres = exprval_value(ctx->parser->script, &exprvalr, ei, &rval);
- exprval_release(&exprvalr);
- }
- if(SUCCEEDED(hres)) {
- hres = oper(ctx, &lval, &rval, ei, &retv);
- VariantClear(&rval);
- }
- VariantClear(&lval);
- }
+ TRACE("\n");
- if(SUCCEEDED(hres)) {
- hres = put_value(ctx->parser->script, &exprval, &retv, ei);
- if(FAILED(hres))
- VariantClear(&retv);
- }
- exprval_release(&exprval);
+ disp = stack_topn_objid(ctx, 0, &id);
+ if(!disp)
+ return throw_reference_error(ctx->script, JS_E_ILLEGAL_ASSIGN, NULL);
+ hres = disp_propget(ctx->script, disp, id, &v);
if(FAILED(hres))
return hres;
- ret->type = EXPRVAL_VARIANT;
- ret->u.var = retv;
- return S_OK;
+ return stack_push(ctx, v);
}
-/* ECMA-262 3rd Edition 13 */
-HRESULT function_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
+/* ECMA-262 3rd Edition 11.2.2 */
+static HRESULT interp_new(exec_ctx_t *ctx)
{
- function_expression_t *expr = (function_expression_t*)_expr;
- VARIANT var;
+ const unsigned argc = get_op_uint(ctx, 0);
+ jsval_t r, constr;
HRESULT hres;
- TRACE("\n");
-
- if(expr->identifier) {
- hres = jsdisp_propget_name(ctx->var_disp, expr->identifier, &var, ei, NULL/*FIXME*/);
- if(FAILED(hres))
- return hres;
- }else {
- DispatchEx *dispex;
-
- hres = create_source_function(ctx->parser, expr->parameter_list, expr->source_elements, ctx->scope_chain,
- expr->src_str, expr->src_len, &dispex);
- if(FAILED(hres))
- return hres;
+ TRACE("%d\n", argc);
- V_VT(&var) = VT_DISPATCH;
- V_DISPATCH(&var) = (IDispatch*)_IDispatchEx_(dispex);
- }
+ constr = stack_topn(ctx, argc);
- ret->type = EXPRVAL_VARIANT;
- ret->u.var = var;
- return S_OK;
-}
+ /* NOTE: Should use to_object here */
-/* ECMA-262 3rd Edition 11.12 */
-HRESULT conditional_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
-{
- conditional_expression_t *expr = (conditional_expression_t*)_expr;
- exprval_t exprval;
- VARIANT_BOOL b;
- HRESULT hres;
-
- TRACE("\n");
+ if(is_null(constr))
+ return throw_type_error(ctx->script, JS_E_OBJECT_EXPECTED, NULL);
+ else if(!is_object_instance(constr))
+ return throw_type_error(ctx->script, JS_E_INVALID_ACTION, NULL);
+ else if(!get_object(constr))
+ return throw_type_error(ctx->script, JS_E_INVALID_PROPERTY, NULL);
- hres = expr_eval(ctx, expr->expression, 0, ei, &exprval);
- if(FAILED(hres))
- return hres;
-
- hres = exprval_to_boolean(ctx->parser->script, &exprval, ei, &b);
- exprval_release(&exprval);
+ hres = disp_call_value(ctx->script, get_object(constr), NULL, DISPATCH_CONSTRUCT, argc, stack_args(ctx, argc), &r);
if(FAILED(hres))
return hres;
- return expr_eval(ctx, b ? expr->true_expression : expr->false_expression, flags, ei, ret);
+ stack_popn(ctx, argc+1);
+ return stack_push(ctx, r);
}
-/* ECMA-262 3rd Edition 11.2.1 */
-HRESULT array_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
+/* ECMA-262 3rd Edition 11.2.3 */
+static HRESULT interp_call(exec_ctx_t *ctx)
{
- array_expression_t *expr = (array_expression_t*)_expr;
- exprval_t exprval;
- VARIANT member, val;
- DISPID id;
- BSTR str;
- IDispatch *obj = NULL;
+ const unsigned argn = get_op_uint(ctx, 0);
+ const int do_ret = get_op_int(ctx, 1);
+ jsval_t r, obj;
HRESULT hres;
- TRACE("\n");
+ TRACE("%d %d\n", argn, do_ret);
- hres = expr_eval(ctx, expr->member_expr, 0, ei, &exprval);
- if(FAILED(hres))
- return hres;
+ obj = stack_topn(ctx, argn);
+ if(!is_object_instance(obj))
+ return throw_type_error(ctx->script, JS_E_INVALID_PROPERTY, NULL);
- hres = exprval_to_value(ctx->parser->script, &exprval, ei, &member);
- exprval_release(&exprval);
+ hres = disp_call_value(ctx->script, get_object(obj), NULL, DISPATCH_METHOD, argn, stack_args(ctx, argn),
+ do_ret ? &r : NULL);
if(FAILED(hres))
return hres;
- hres = expr_eval(ctx, expr->expression, EXPR_NEWREF, ei, &exprval);
- if(SUCCEEDED(hres)) {
- hres = exprval_to_value(ctx->parser->script, &exprval, ei, &val);
- exprval_release(&exprval);
- }
-
- if(SUCCEEDED(hres)) {
- hres = to_object(ctx->parser->script, &member, &obj);
- if(FAILED(hres))
- VariantClear(&val);
- }
- VariantClear(&member);
- if(SUCCEEDED(hres)) {
- hres = to_string(ctx->parser->script, &val, ei, &str);
- VariantClear(&val);
- if(SUCCEEDED(hres)) {
- if(flags & EXPR_STRREF) {
- ret->type = EXPRVAL_NAMEREF;
- ret->u.nameref.disp = obj;
- ret->u.nameref.name = str;
- return S_OK;
- }
-
- hres = disp_get_id(ctx->parser->script, obj, str, flags & EXPR_NEWREF ? fdexNameEnsure : 0, &id);
- SysFreeString(str);
- }
-
- if(SUCCEEDED(hres)) {
- exprval_set_idref(ret, obj, id);
- }else if(!(flags & EXPR_NEWREF) && hres == DISP_E_UNKNOWNNAME) {
- exprval_init(ret);
- hres = S_OK;
- }
-
- IDispatch_Release(obj);
- }
-
- return hres;
+ stack_popn(ctx, argn+1);
+ return do_ret ? stack_push(ctx, r) : S_OK;
}
-/* ECMA-262 3rd Edition 11.2.1 */
-HRESULT member_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
+/* ECMA-262 3rd Edition 11.2.3 */
+static HRESULT interp_call_member(exec_ctx_t *ctx)
{
- member_expression_t *expr = (member_expression_t*)_expr;
- IDispatch *obj = NULL;
- exprval_t exprval;
- VARIANT member;
+ const unsigned argn = get_op_uint(ctx, 0);
+ const int do_ret = get_op_int(ctx, 1);
+ IDispatch *obj;
+ jsval_t r;
DISPID id;
- BSTR str;
HRESULT hres;
- TRACE("\n");
-
- hres = expr_eval(ctx, expr->expression, 0, ei, &exprval);
- if(FAILED(hres))
- return hres;
+ TRACE("%d %d\n", argn, do_ret);
- hres = exprval_to_value(ctx->parser->script, &exprval, ei, &member);
- exprval_release(&exprval);
- if(FAILED(hres))
- return hres;
+ obj = stack_topn_objid(ctx, argn, &id);
+ if(!obj)
+ return throw_type_error(ctx->script, id, NULL);
- hres = to_object(ctx->parser->script, &member, &obj);
- VariantClear(&member);
+ hres = disp_call(ctx->script, obj, id, DISPATCH_METHOD, argn, stack_args(ctx, argn), do_ret ? &r : NULL);
if(FAILED(hres))
return hres;
- str = SysAllocString(expr->identifier);
- if(flags & EXPR_STRREF) {
- ret->type = EXPRVAL_NAMEREF;
- ret->u.nameref.disp = obj;
- ret->u.nameref.name = str;
- return S_OK;
- }
-
- hres = disp_get_id(ctx->parser->script, obj, str, flags & EXPR_NEWREF ? fdexNameEnsure : 0, &id);
- SysFreeString(str);
- if(SUCCEEDED(hres)) {
- exprval_set_idref(ret, obj, id);
- }else if(!(flags & EXPR_NEWREF) && hres == DISP_E_UNKNOWNNAME) {
- exprval_init(ret);
- hres = S_OK;
- }
-
- IDispatch_Release(obj);
- return hres;
-}
-
-static void free_dp(DISPPARAMS *dp)
-{
- DWORD i;
+ stack_popn(ctx, argn+2);
+ return do_ret ? stack_push(ctx, r) : S_OK;
- for(i=0; i < dp->cArgs; i++)
- VariantClear(dp->rgvarg+i);
- heap_free(dp->rgvarg);
}
-static HRESULT args_to_param(exec_ctx_t *ctx, argument_t *args, jsexcept_t *ei, DISPPARAMS *dp)
+/* ECMA-262 3rd Edition 11.1.1 */
+static HRESULT interp_this(exec_ctx_t *ctx)
{
- VARIANTARG *vargs;
- exprval_t exprval;
- argument_t *iter;
- DWORD cnt = 0, i;
- HRESULT hres = S_OK;
-
- memset(dp, 0, sizeof(*dp));
- if(!args)
- return S_OK;
-
- for(iter = args; iter; iter = iter->next)
- cnt++;
-
- vargs = heap_alloc_zero(cnt * sizeof(*vargs));
- if(!vargs)
- return E_OUTOFMEMORY;
-
- for(i = cnt, iter = args; iter; iter = iter->next) {
- hres = expr_eval(ctx, iter->expr, 0, ei, &exprval);
- if(FAILED(hres))
- break;
-
- hres = exprval_to_value(ctx->parser->script, &exprval, ei, vargs + (--i));
- exprval_release(&exprval);
- if(FAILED(hres))
- break;
- }
-
- if(FAILED(hres)) {
- free_dp(dp);
- return hres;
- }
+ TRACE("\n");
- dp->rgvarg = vargs;
- dp->cArgs = cnt;
- return S_OK;
+ IDispatch_AddRef(ctx->this_obj);
+ return stack_push(ctx, jsval_disp(ctx->this_obj));
}
-/* ECMA-262 3rd Edition 11.2.2 */
-HRESULT new_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
+/* ECMA-262 3rd Edition 10.1.4 */
+static HRESULT interp_ident(exec_ctx_t *ctx)
{
- call_expression_t *expr = (call_expression_t*)_expr;
+ const BSTR arg = get_op_bstr(ctx, 0);
exprval_t exprval;
- VARIANT constr, var;
- DISPPARAMS dp;
+ jsval_t v;
HRESULT hres;
- TRACE("\n");
-
- hres = expr_eval(ctx, expr->expression, 0, ei, &exprval);
- if(FAILED(hres))
- return hres;
+ TRACE("%s\n", debugstr_w(arg));
- hres = args_to_param(ctx, expr->argument_list, ei, &dp);
- if(SUCCEEDED(hres))
- hres = exprval_to_value(ctx->parser->script, &exprval, ei, &constr);
- exprval_release(&exprval);
+ hres = identifier_eval(ctx->script, arg, &exprval);
if(FAILED(hres))
return hres;
- if(V_VT(&constr) != VT_DISPATCH) {
- FIXME("throw TypeError\n");
- VariantClear(&constr);
- return E_FAIL;
- }
+ if(exprval.type == EXPRVAL_INVALID)
+ return throw_type_error(ctx->script, JS_E_UNDEFINED_VARIABLE, arg);
- hres = disp_call(ctx->parser->script, V_DISPATCH(&constr), DISPID_VALUE,
- DISPATCH_CONSTRUCT, &dp, &var, ei, NULL/*FIXME*/);
- IDispatch_Release(V_DISPATCH(&constr));
- free_dp(&dp);
+ hres = exprval_to_value(ctx->script, &exprval, &v);
+ exprval_release(&exprval);
if(FAILED(hres))
return hres;
- ret->type = EXPRVAL_VARIANT;
- ret->u.var = var;
- return S_OK;
+ return stack_push(ctx, v);
}
-/* ECMA-262 3rd Edition 11.2.3 */
-HRESULT call_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
+/* ECMA-262 3rd Edition 10.1.4 */
+static HRESULT interp_identid(exec_ctx_t *ctx)
{
- call_expression_t *expr = (call_expression_t*)_expr;
- VARIANT var;
+ const BSTR arg = get_op_bstr(ctx, 0);
+ const unsigned flags = get_op_uint(ctx, 1);
exprval_t exprval;
- DISPPARAMS dp;
HRESULT hres;
- TRACE("\n");
+ TRACE("%s %x\n", debugstr_w(arg), flags);
- hres = expr_eval(ctx, expr->expression, 0, ei, &exprval);
+ hres = identifier_eval(ctx->script, arg, &exprval);
if(FAILED(hres))
return hres;
- hres = args_to_param(ctx, expr->argument_list, ei, &dp);
- if(SUCCEEDED(hres)) {
- switch(exprval.type) {
- case EXPRVAL_VARIANT:
- if(V_VT(&exprval.u.var) == VT_DISPATCH)
- hres = disp_call(ctx->parser->script, V_DISPATCH(&exprval.u.var), DISPID_VALUE,
- DISPATCH_METHOD, &dp, flags & EXPR_NOVAL ? NULL : &var, ei, NULL/*FIXME*/);
- else
- hres = throw_type_error(ctx->parser->script, ei, IDS_NO_PROPERTY, NULL);
- break;
- case EXPRVAL_IDREF:
- hres = disp_call(ctx->parser->script, exprval.u.idref.disp, exprval.u.idref.id,
- DISPATCH_METHOD, &dp, flags & EXPR_NOVAL ? NULL : &var, ei, NULL/*FIXME*/);
- break;
- case EXPRVAL_INVALID:
- hres = throw_type_error(ctx->parser->script, ei, IDS_OBJECT_EXPECTED, NULL);
- break;
- default:
- FIXME("unimplemented type %d\n", exprval.type);
- hres = E_NOTIMPL;
- }
-
- free_dp(&dp);
- }
+ if(exprval.type == EXPRVAL_INVALID && (flags & fdexNameEnsure)) {
+ DISPID id;
- exprval_release(&exprval);
- if(FAILED(hres))
- return hres;
+ hres = jsdisp_get_id(ctx->script->global, arg, fdexNameEnsure, &id);
+ if(FAILED(hres))
+ return hres;
- ret->type = EXPRVAL_VARIANT;
- if(flags & EXPR_NOVAL) {
- V_VT(&ret->u.var) = VT_EMPTY;
- }else {
- TRACE("= %s\n", debugstr_variant(&var));
- ret->u.var = var;
+ exprval_set_idref(&exprval, to_disp(ctx->script->global), id);
}
- return S_OK;
-}
-/* ECMA-262 3rd Edition 11.1.1 */
-HRESULT this_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
-{
- TRACE("\n");
+ if(exprval.type != EXPRVAL_IDREF) {
+ WARN("invalid ref\n");
+ exprval_release(&exprval);
+ return stack_push_objid(ctx, NULL, JS_E_OBJECT_EXPECTED);
+ }
- ret->type = EXPRVAL_VARIANT;
- V_VT(&ret->u.var) = VT_DISPATCH;
- V_DISPATCH(&ret->u.var) = ctx->this_obj;
- IDispatch_AddRef(ctx->this_obj);
- return S_OK;
+ return stack_push_objid(ctx, exprval.u.idref.disp, exprval.u.idref.id);
}
-/* ECMA-262 3rd Edition 10.1.4 */
-HRESULT identifier_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
+/* ECMA-262 3rd Edition 7.8.1 */
+static HRESULT interp_null(exec_ctx_t *ctx)
{
- identifier_expression_t *expr = (identifier_expression_t*)_expr;
- BSTR identifier;
- HRESULT hres;
-
TRACE("\n");
- identifier = SysAllocString(expr->identifier);
- if(!identifier)
- return E_OUTOFMEMORY;
-
- hres = identifier_eval(ctx, identifier, flags, ei, ret);
-
- SysFreeString(identifier);
- return hres;
+ return stack_push(ctx, jsval_null());
}
-/* ECMA-262 3rd Edition 7.8 */
-HRESULT literal_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
+/* ECMA-262 3rd Edition 7.8.2 */
+static HRESULT interp_bool(exec_ctx_t *ctx)
{
- literal_expression_t *expr = (literal_expression_t*)_expr;
- VARIANT var;
- HRESULT hres;
+ const int arg = get_op_int(ctx, 0);
- TRACE("\n");
+ TRACE("%s\n", arg ? "true" : "false");
- hres = literal_to_var(ctx->parser->script, expr->literal, &var);
- if(FAILED(hres))
- return hres;
-
- ret->type = EXPRVAL_VARIANT;
- ret->u.var = var;
- return S_OK;
+ return stack_push(ctx, jsval_bool(arg));
}
-/* ECMA-262 3rd Edition 11.1.4 */
-HRESULT array_literal_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
+/* ECMA-262 3rd Edition 7.8.3 */
+static HRESULT interp_int(exec_ctx_t *ctx)
{
- array_literal_expression_t *expr = (array_literal_expression_t*)_expr;
- DWORD length = 0, i = 0;
- array_element_t *elem;
- DispatchEx *array;
- exprval_t exprval;
- VARIANT val;
- HRESULT hres;
-
- TRACE("\n");
-
- for(elem = expr->element_list; elem; elem = elem->next)
- length += elem->elision+1;
- length += expr->length;
-
- hres = create_array(ctx->parser->script, length, &array);
- if(FAILED(hres))
- return hres;
-
- for(elem = expr->element_list; elem; elem = elem->next) {
- i += elem->elision;
-
- hres = expr_eval(ctx, elem->expr, 0, ei, &exprval);
- if(FAILED(hres))
- break;
-
- hres = exprval_to_value(ctx->parser->script, &exprval, ei, &val);
- exprval_release(&exprval);
- if(FAILED(hres))
- break;
+ const int arg = get_op_int(ctx, 0);
- hres = jsdisp_propput_idx(array, i, &val, ei, NULL/*FIXME*/);
- VariantClear(&val);
- if(FAILED(hres))
- break;
-
- i++;
- }
-
- if(FAILED(hres)) {
- jsdisp_release(array);
- return hres;
- }
+ TRACE("%d\n", arg);
- ret->type = EXPRVAL_VARIANT;
- V_VT(&ret->u.var) = VT_DISPATCH;
- V_DISPATCH(&ret->u.var) = (IDispatch*)_IDispatchEx_(array);
- return S_OK;
+ return stack_push(ctx, jsval_number(arg));
}
-/* ECMA-262 3rd Edition 11.1.5 */
-HRESULT property_value_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
+/* ECMA-262 3rd Edition 7.8.3 */
+static HRESULT interp_double(exec_ctx_t *ctx)
{
- property_value_expression_t *expr = (property_value_expression_t*)_expr;
- VARIANT val, tmp;
- DispatchEx *obj;
- prop_val_t *iter;
- exprval_t exprval;
- BSTR name;
- HRESULT hres;
+ const double arg = get_op_double(ctx);
- TRACE("\n");
+ TRACE("%lf\n", arg);
- hres = create_object(ctx->parser->script, NULL, &obj);
- if(FAILED(hres))
- return hres;
+ return stack_push(ctx, jsval_number(arg));
+}
- for(iter = expr->property_list; iter; iter = iter->next) {
- hres = literal_to_var(ctx->parser->script, iter->name, &tmp);
- if(FAILED(hres))
- break;
+/* ECMA-262 3rd Edition 7.8.4 */
+static HRESULT interp_str(exec_ctx_t *ctx)
+{
+ jsstr_t *str = get_op_str(ctx, 0);
- hres = to_string(ctx->parser->script, &tmp, ei, &name);
- VariantClear(&tmp);
- if(FAILED(hres))
- break;
+ TRACE("%s\n", debugstr_jsstr(str));
- hres = expr_eval(ctx, iter->value, 0, ei, &exprval);
- if(SUCCEEDED(hres)) {
- hres = exprval_to_value(ctx->parser->script, &exprval, ei, &val);
- exprval_release(&exprval);
- if(SUCCEEDED(hres)) {
- hres = jsdisp_propput_name(obj, name, &val, ei, NULL/*FIXME*/);
- VariantClear(&val);
- }
- }
+ return stack_push(ctx, jsval_string(jsstr_addref(str)));
+}
- SysFreeString(name);
- if(FAILED(hres))
- break;
- }
+/* ECMA-262 3rd Edition 7.8 */
+static HRESULT interp_regexp(exec_ctx_t *ctx)
+{
+ jsstr_t *source = get_op_str(ctx, 0);
+ const unsigned flags = get_op_uint(ctx, 1);
+ jsdisp_t *regexp;
+ HRESULT hres;
- if(FAILED(hres)) {
- jsdisp_release(obj);
+ TRACE("%s %x\n", debugstr_jsstr(source), flags);
+
+ hres = create_regexp(ctx->script, source, flags, ®exp);
+ if(FAILED(hres))
return hres;
- }
- ret->type = EXPRVAL_VARIANT;
- V_VT(&ret->u.var) = VT_DISPATCH;
- V_DISPATCH(&ret->u.var) = (IDispatch*)_IDispatchEx_(obj);
- return S_OK;
+ return stack_push(ctx, jsval_obj(regexp));
}
-/* ECMA-262 3rd Edition 11.14 */
-HRESULT comma_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
+/* ECMA-262 3rd Edition 11.1.4 */
+static HRESULT interp_carray(exec_ctx_t *ctx)
{
- binary_expression_t *expr = (binary_expression_t*)_expr;
- VARIANT lval, rval;
+ const unsigned arg = get_op_uint(ctx, 0);
+ jsdisp_t *array;
+ jsval_t val;
+ unsigned i;
HRESULT hres;
- TRACE("\n");
+ TRACE("%u\n", arg);
- hres = get_binary_expr_values(ctx, expr, ei, &lval, &rval);
+ hres = create_array(ctx->script, arg, &array);
if(FAILED(hres))
return hres;
- VariantClear(&lval);
+ i = arg;
+ while(i--) {
+ val = stack_pop(ctx);
+ hres = jsdisp_propput_idx(array, i, val);
+ jsval_release(val);
+ if(FAILED(hres)) {
+ jsdisp_release(array);
+ return hres;
+ }
+ }
- ret->type = EXPRVAL_VARIANT;
- ret->u.var = rval;
- return S_OK;
+ return stack_push(ctx, jsval_obj(array));
}
-/* ECMA-262 3rd Edition 11.11 */
-HRESULT logical_or_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
+/* ECMA-262 3rd Edition 11.1.5 */
+static HRESULT interp_new_obj(exec_ctx_t *ctx)
{
- binary_expression_t *expr = (binary_expression_t*)_expr;
- exprval_t exprval;
- VARIANT_BOOL b;
- VARIANT val;
+ jsdisp_t *obj;
HRESULT hres;
TRACE("\n");
- hres = expr_eval(ctx, expr->expression1, 0, ei, &exprval);
+ hres = create_object(ctx->script, NULL, &obj);
if(FAILED(hres))
return hres;
- hres = exprval_to_value(ctx->parser->script, &exprval, ei, &val);
- exprval_release(&exprval);
- if(FAILED(hres))
- return hres;
+ return stack_push(ctx, jsval_obj(obj));
+}
- hres = to_boolean(&val, &b);
- if(SUCCEEDED(hres) && b) {
- ret->type = EXPRVAL_VARIANT;
- ret->u.var = val;
- return S_OK;
- }
+/* ECMA-262 3rd Edition 11.1.5 */
+static HRESULT interp_obj_prop(exec_ctx_t *ctx)
+{
+ const BSTR name = get_op_bstr(ctx, 0);
+ jsdisp_t *obj;
+ jsval_t val;
+ HRESULT hres;
- VariantClear(&val);
- if(FAILED(hres))
- return hres;
+ TRACE("%s\n", debugstr_w(name));
- hres = expr_eval(ctx, expr->expression2, 0, ei, &exprval);
- if(FAILED(hres))
- return hres;
+ val = stack_pop(ctx);
- hres = exprval_to_value(ctx->parser->script, &exprval, ei, &val);
- exprval_release(&exprval);
- if(FAILED(hres))
- return hres;
+ assert(is_object_instance(stack_top(ctx)));
+ obj = as_jsdisp(get_object(stack_top(ctx)));
- ret->type = EXPRVAL_VARIANT;
- ret->u.var = val;
- return S_OK;
+ hres = jsdisp_propput_name(obj, name, val);
+ jsval_release(val);
+ return hres;
}
/* ECMA-262 3rd Edition 11.11 */
-HRESULT logical_and_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
+static HRESULT interp_cnd_nz(exec_ctx_t *ctx)
{
- binary_expression_t *expr = (binary_expression_t*)_expr;
- exprval_t exprval;
- VARIANT_BOOL b;
- VARIANT val;
+ const unsigned arg = get_op_uint(ctx, 0);
+ BOOL b;
HRESULT hres;
TRACE("\n");
- hres = expr_eval(ctx, expr->expression1, 0, ei, &exprval);
+ hres = to_boolean(stack_top(ctx), &b);
if(FAILED(hres))
return hres;
- hres = exprval_to_value(ctx->parser->script, &exprval, ei, &val);
- exprval_release(&exprval);
- if(FAILED(hres))
- return hres;
-
- hres = to_boolean(&val, &b);
- if(SUCCEEDED(hres) && !b) {
- ret->type = EXPRVAL_VARIANT;
- ret->u.var = val;
- return S_OK;
+ if(b) {
+ ctx->ip = arg;
+ }else {
+ stack_popn(ctx, 1);
+ ctx->ip++;
}
+ return S_OK;
+}
- VariantClear(&val);
- if(FAILED(hres))
- return hres;
+/* ECMA-262 3rd Edition 11.11 */
+static HRESULT interp_cnd_z(exec_ctx_t *ctx)
+{
+ const unsigned arg = get_op_uint(ctx, 0);
+ BOOL b;
+ HRESULT hres;
- hres = expr_eval(ctx, expr->expression2, 0, ei, &exprval);
- if(FAILED(hres))
- return hres;
+ TRACE("\n");
- hres = exprval_to_value(ctx->parser->script, &exprval, ei, &val);
- exprval_release(&exprval);
+ hres = to_boolean(stack_top(ctx), &b);
if(FAILED(hres))
return hres;
- ret->type = EXPRVAL_VARIANT;
- ret->u.var = val;
+ if(b) {
+ stack_popn(ctx, 1);
+ ctx->ip++;
+ }else {
+ ctx->ip = arg;
+ }
return S_OK;
}
/* ECMA-262 3rd Edition 11.10 */
-static HRESULT bitor_eval(exec_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexcept_t *ei, VARIANT *retv)
+static HRESULT interp_or(exec_ctx_t *ctx)
{
- INT li, ri;
+ INT l, r;
HRESULT hres;
- hres = to_int32(ctx->parser->script, lval, ei, &li);
+ TRACE("\n");
+
+ hres = stack_pop_int(ctx, &r);
if(FAILED(hres))
return hres;
- hres = to_int32(ctx->parser->script, rval, ei, &ri);
+ hres = stack_pop_int(ctx, &l);
if(FAILED(hres))
return hres;
- V_VT(retv) = VT_I4;
- V_I4(retv) = li|ri;
- return S_OK;
+ return stack_push(ctx, jsval_number(l|r));
}
/* ECMA-262 3rd Edition 11.10 */
-HRESULT binary_or_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
+static HRESULT interp_xor(exec_ctx_t *ctx)
{
- binary_expression_t *expr = (binary_expression_t*)_expr;
+ INT l, r;
+ HRESULT hres;
TRACE("\n");
- return binary_expr_eval(ctx, expr, bitor_eval, ei, ret);
-}
-
-/* ECMA-262 3rd Edition 11.10 */
-static HRESULT xor_eval(exec_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexcept_t *ei, VARIANT *retv)
-{
- INT li, ri;
- HRESULT hres;
-
- hres = to_int32(ctx->parser->script, lval, ei, &li);
+ hres = stack_pop_int(ctx, &r);
if(FAILED(hres))
return hres;
- hres = to_int32(ctx->parser->script, rval, ei, &ri);
+ hres = stack_pop_int(ctx, &l);
if(FAILED(hres))
return hres;
- V_VT(retv) = VT_I4;
- V_I4(retv) = li^ri;
- return S_OK;
+ return stack_push(ctx, jsval_number(l^r));
}
/* ECMA-262 3rd Edition 11.10 */
-HRESULT binary_xor_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
+static HRESULT interp_and(exec_ctx_t *ctx)
{
- binary_expression_t *expr = (binary_expression_t*)_expr;
+ INT l, r;
+ HRESULT hres;
TRACE("\n");
- return binary_expr_eval(ctx, expr, xor_eval, ei, ret);
-}
-
-/* ECMA-262 3rd Edition 11.10 */
-static HRESULT bitand_eval(exec_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexcept_t *ei, VARIANT *retv)
-{
- INT li, ri;
- HRESULT hres;
-
- hres = to_int32(ctx->parser->script, lval, ei, &li);
+ hres = stack_pop_int(ctx, &r);
if(FAILED(hres))
return hres;
- hres = to_int32(ctx->parser->script, rval, ei, &ri);
+ hres = stack_pop_int(ctx, &l);
if(FAILED(hres))
return hres;
- V_VT(retv) = VT_I4;
- V_I4(retv) = li&ri;
- return S_OK;
-}
-
-/* ECMA-262 3rd Edition 11.10 */
-HRESULT binary_and_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
-{
- binary_expression_t *expr = (binary_expression_t*)_expr;
-
- TRACE("\n");
-
- return binary_expr_eval(ctx, expr, bitand_eval, ei, ret);
+ return stack_push(ctx, jsval_number(l&r));
}
/* ECMA-262 3rd Edition 11.8.6 */
-static HRESULT instanceof_eval(exec_ctx_t *ctx, VARIANT *inst, VARIANT *objv, jsexcept_t *ei, VARIANT *retv)
+static HRESULT interp_instanceof(exec_ctx_t *ctx)
{
- DispatchEx *obj, *iter, *tmp = NULL;
- VARIANT_BOOL ret = VARIANT_FALSE;
- BOOL b;
- VARIANT var;
+ jsdisp_t *obj, *iter, *tmp = NULL;
+ jsval_t prot, v;
+ BOOL ret = FALSE;
HRESULT hres;
static const WCHAR prototypeW[] = {'p','r','o','t','o','t', 'y', 'p','e',0};
- if(V_VT(objv) != VT_DISPATCH) {
- FIXME("throw TypeError\n");
- return E_FAIL;
+ v = stack_pop(ctx);
+ if(!is_object_instance(v) || !get_object(v)) {
+ jsval_release(v);
+ return throw_type_error(ctx->script, JS_E_FUNCTION_EXPECTED, NULL);
}
- obj = iface_to_jsdisp((IUnknown*)V_DISPATCH(objv));
+ obj = iface_to_jsdisp((IUnknown*)get_object(v));
+ IDispatch_Release(get_object(v));
if(!obj) {
- FIXME("throw TypeError\n");
+ FIXME("non-jsdisp objects not supported\n");
return E_FAIL;
}
if(is_class(obj, JSCLASS_FUNCTION)) {
- hres = jsdisp_propget_name(obj, prototypeW, &var, ei, NULL/*FIXME*/);
+ hres = jsdisp_propget_name(obj, prototypeW, &prot);
}else {
- FIXME("throw TypeError\n");
- hres = E_FAIL;
+ hres = throw_type_error(ctx->script, JS_E_FUNCTION_EXPECTED, NULL);
}
jsdisp_release(obj);
if(FAILED(hres))
return hres;
- if(V_VT(&var) == VT_DISPATCH) {
- if(V_VT(inst) == VT_DISPATCH)
- tmp = iface_to_jsdisp((IUnknown*)V_DISPATCH(inst));
- for(iter = tmp; iter; iter = iter->prototype) {
- hres = disp_cmp(V_DISPATCH(&var), (IDispatch*)_IDispatchEx_(iter), &b);
+ v = stack_pop(ctx);
+
+ if(is_object_instance(prot)) {
+ if(is_object_instance(v))
+ tmp = iface_to_jsdisp((IUnknown*)get_object(v));
+ for(iter = tmp; !ret && iter; iter = iter->prototype) {
+ hres = disp_cmp(get_object(prot), to_disp(iter), &ret);
if(FAILED(hres))
break;
- if(b) {
- ret = VARIANT_TRUE;
- break;
- }
}
if(tmp)
hres = E_FAIL;
}
- VariantClear(&var);
+ jsval_release(prot);
+ jsval_release(v);
if(FAILED(hres))
return hres;
- V_VT(retv) = VT_BOOL;
- V_BOOL(retv) = ret;
- return S_OK;
-}
-
-/* ECMA-262 3rd Edition 11.8.6 */
-HRESULT instanceof_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
-{
- binary_expression_t *expr = (binary_expression_t*)_expr;
-
- TRACE("\n");
-
- return binary_expr_eval(ctx, expr, instanceof_eval, ei, ret);
+ return stack_push(ctx, jsval_bool(ret));
}
/* ECMA-262 3rd Edition 11.8.7 */
-static HRESULT in_eval(exec_ctx_t *ctx, VARIANT *lval, VARIANT *obj, jsexcept_t *ei, VARIANT *retv)
+static HRESULT interp_in(exec_ctx_t *ctx)
{
- VARIANT_BOOL ret;
- DISPID id;
- BSTR str;
+ jsval_t obj, v;
+ DISPID id = 0;
+ BOOL ret;
+ jsstr_t *str;
HRESULT hres;
- if(V_VT(obj) != VT_DISPATCH) {
- FIXME("throw TypeError\n");
- return E_FAIL;
+ TRACE("\n");
+
+ obj = stack_pop(ctx);
+ if(!is_object_instance(obj) || !get_object(obj)) {
+ jsval_release(obj);
+ return throw_type_error(ctx->script, JS_E_OBJECT_EXPECTED, NULL);
}
- hres = to_string(ctx->parser->script, lval, ei, &str);
- if(FAILED(hres))
+ v = stack_pop(ctx);
+ hres = to_string(ctx->script, v, &str);
+ jsval_release(v);
+ if(FAILED(hres)) {
+ IDispatch_Release(get_object(obj));
return hres;
+ }
- hres = disp_get_id(ctx->parser->script, V_DISPATCH(obj), str, 0, &id);
- SysFreeString(str);
+ hres = disp_get_id(ctx->script, get_object(obj), str->str, NULL, 0, &id);
+ IDispatch_Release(get_object(obj));
+ jsstr_release(str);
if(SUCCEEDED(hres))
- ret = VARIANT_TRUE;
+ ret = TRUE;
else if(hres == DISP_E_UNKNOWNNAME)
- ret = VARIANT_FALSE;
+ ret = FALSE;
else
return hres;
- V_VT(retv) = VT_BOOL;
- V_BOOL(retv) = ret;
- return S_OK;
-}
-
-/* ECMA-262 3rd Edition 11.8.7 */
-HRESULT in_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
-{
- binary_expression_t *expr = (binary_expression_t*)_expr;
-
- TRACE("\n");
-
- return binary_expr_eval(ctx, expr, in_eval, ei, ret);
+ return stack_push(ctx, jsval_bool(ret));
}
/* ECMA-262 3rd Edition 11.6.1 */
-static HRESULT add_eval(exec_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexcept_t *ei, VARIANT *retv)
+static HRESULT add_eval(script_ctx_t *ctx, jsval_t lval, jsval_t rval, jsval_t *ret)
{
- VARIANT r, l;
+ jsval_t r, l;
HRESULT hres;
- hres = to_primitive(ctx->parser->script, lval, ei, &l, NO_HINT);
+ hres = to_primitive(ctx, lval, &l, NO_HINT);
if(FAILED(hres))
return hres;
- hres = to_primitive(ctx->parser->script, rval, ei, &r, NO_HINT);
+ hres = to_primitive(ctx, rval, &r, NO_HINT);
if(FAILED(hres)) {
- VariantClear(&l);
+ jsval_release(l);
return hres;
}
- if(V_VT(&l) == VT_BSTR || V_VT(&r) == VT_BSTR) {
- BSTR lstr = NULL, rstr = NULL;
+ if(is_string(l) || is_string(r)) {
+ jsstr_t *lstr, *rstr = NULL;
- if(V_VT(&l) == VT_BSTR)
- lstr = V_BSTR(&l);
- else
- hres = to_string(ctx->parser->script, &l, ei, &lstr);
-
- if(SUCCEEDED(hres)) {
- if(V_VT(&r) == VT_BSTR)
- rstr = V_BSTR(&r);
- else
- hres = to_string(ctx->parser->script, &r, ei, &rstr);
- }
+ hres = to_string(ctx, l, &lstr);
+ if(SUCCEEDED(hres))
+ hres = to_string(ctx, r, &rstr);
if(SUCCEEDED(hres)) {
- int len1, len2;
+ jsstr_t *ret_str;
- len1 = SysStringLen(lstr);
- len2 = SysStringLen(rstr);
-
- V_VT(retv) = VT_BSTR;
- V_BSTR(retv) = SysAllocStringLen(NULL, len1+len2);
- memcpy(V_BSTR(retv), lstr, len1*sizeof(WCHAR));
- memcpy(V_BSTR(retv)+len1, rstr, (len2+1)*sizeof(WCHAR));
+ ret_str = jsstr_concat(lstr, rstr);
+ if(ret_str)
+ *ret = jsval_string(ret_str);
+ else
+ hres = E_OUTOFMEMORY;
}
- if(V_VT(&l) != VT_BSTR)
- SysFreeString(lstr);
- if(V_VT(&r) != VT_BSTR)
- SysFreeString(rstr);
+ jsstr_release(lstr);
+ if(rstr)
+ jsstr_release(rstr);
}else {
- VARIANT nl, nr;
+ double nl, nr;
- hres = to_number(ctx->parser->script, &l, ei, &nl);
+ hres = to_number(ctx, l, &nl);
if(SUCCEEDED(hres)) {
- hres = to_number(ctx->parser->script, &r, ei, &nr);
+ hres = to_number(ctx, r, &nr);
if(SUCCEEDED(hres))
- num_set_val(retv, num_val(&nl) + num_val(&nr));
+ *ret = jsval_number(nl+nr);
}
}
- VariantClear(&r);
- VariantClear(&l);
+ jsval_release(r);
+ jsval_release(l);
return hres;
}
/* ECMA-262 3rd Edition 11.6.1 */
-HRESULT add_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
-{
- binary_expression_t *expr = (binary_expression_t*)_expr;
-
- TRACE("\n");
-
- return binary_expr_eval(ctx, expr, add_eval, ei, ret);
-}
-
-/* ECMA-262 3rd Edition 11.6.2 */
-static HRESULT sub_eval(exec_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexcept_t *ei, VARIANT *retv)
+static HRESULT interp_add(exec_ctx_t *ctx)
{
- VARIANT lnum, rnum;
+ jsval_t l, r, ret;
HRESULT hres;
- hres = to_number(ctx->parser->script, lval, ei, &lnum);
- if(FAILED(hres))
- return hres;
+ r = stack_pop(ctx);
+ l = stack_pop(ctx);
+
+ TRACE("%s + %s\n", debugstr_jsval(l), debugstr_jsval(r));
- hres = to_number(ctx->parser->script, rval, ei, &rnum);
+ hres = add_eval(ctx->script, l, r, &ret);
+ jsval_release(l);
+ jsval_release(r);
if(FAILED(hres))
return hres;
- num_set_val(retv, num_val(&lnum) - num_val(&rnum));
- return S_OK;
+ return stack_push(ctx, ret);
}
/* ECMA-262 3rd Edition 11.6.2 */
-HRESULT sub_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
+static HRESULT interp_sub(exec_ctx_t *ctx)
{
- binary_expression_t *expr = (binary_expression_t*)_expr;
+ double l, r;
+ HRESULT hres;
TRACE("\n");
- return binary_expr_eval(ctx, expr, sub_eval, ei, ret);
-}
-
-/* ECMA-262 3rd Edition 11.5.1 */
-static HRESULT mul_eval(exec_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexcept_t *ei, VARIANT *retv)
-{
- VARIANT lnum, rnum;
- HRESULT hres;
-
- hres = to_number(ctx->parser->script, lval, ei, &lnum);
+ hres = stack_pop_number(ctx, &r);
if(FAILED(hres))
return hres;
- hres = to_number(ctx->parser->script, rval, ei, &rnum);
+ hres = stack_pop_number(ctx, &l);
if(FAILED(hres))
return hres;
- num_set_val(retv, num_val(&lnum) * num_val(&rnum));
- return S_OK;
+ return stack_push(ctx, jsval_number(l-r));
}
/* ECMA-262 3rd Edition 11.5.1 */
-HRESULT mul_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
+static HRESULT interp_mul(exec_ctx_t *ctx)
{
- binary_expression_t *expr = (binary_expression_t*)_expr;
+ double l, r;
+ HRESULT hres;
TRACE("\n");
- return binary_expr_eval(ctx, expr, mul_eval, ei, ret);
-}
-
-/* ECMA-262 3rd Edition 11.5.2 */
-static HRESULT div_eval(exec_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexcept_t *ei, VARIANT *retv)
-{
- VARIANT lnum, rnum;
- HRESULT hres;
-
- hres = to_number(ctx->parser->script, lval, ei, &lnum);
+ hres = stack_pop_number(ctx, &r);
if(FAILED(hres))
return hres;
- hres = to_number(ctx->parser->script, rval, ei, &rnum);
+ hres = stack_pop_number(ctx, &l);
if(FAILED(hres))
return hres;
- num_set_val(retv, num_val(&lnum) / num_val(&rnum));
- return S_OK;
+ return stack_push(ctx, jsval_number(l*r));
}
/* ECMA-262 3rd Edition 11.5.2 */
-HRESULT div_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
+static HRESULT interp_div(exec_ctx_t *ctx)
{
- binary_expression_t *expr = (binary_expression_t*)_expr;
+ double l, r;
+ HRESULT hres;
TRACE("\n");
- return binary_expr_eval(ctx, expr, div_eval, ei, ret);
-}
-
-/* ECMA-262 3rd Edition 11.5.3 */
-static HRESULT mod_eval(exec_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexcept_t *ei, VARIANT *retv)
-{
- VARIANT lnum, rnum;
- HRESULT hres;
-
- hres = to_number(ctx->parser->script, lval, ei, &lnum);
+ hres = stack_pop_number(ctx, &r);
if(FAILED(hres))
return hres;
- hres = to_number(ctx->parser->script, rval, ei, &rnum);
+ hres = stack_pop_number(ctx, &l);
if(FAILED(hres))
return hres;
- num_set_val(retv, fmod(num_val(&lnum), num_val(&rnum)));
- return S_OK;
+ return stack_push(ctx, jsval_number(l/r));
}
/* ECMA-262 3rd Edition 11.5.3 */
-HRESULT mod_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
+static HRESULT interp_mod(exec_ctx_t *ctx)
{
- binary_expression_t *expr = (binary_expression_t*)_expr;
+ double l, r;
+ HRESULT hres;
TRACE("\n");
- return binary_expr_eval(ctx, expr, mod_eval, ei, ret);
+ hres = stack_pop_number(ctx, &r);
+ if(FAILED(hres))
+ return hres;
+
+ hres = stack_pop_number(ctx, &l);
+ if(FAILED(hres))
+ return hres;
+
+ return stack_push(ctx, jsval_number(fmod(l, r)));
}
/* ECMA-262 3rd Edition 11.4.2 */
-HRESULT delete_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
+static HRESULT interp_delete(exec_ctx_t *ctx)
{
- unary_expression_t *expr = (unary_expression_t*)_expr;
- VARIANT_BOOL b = VARIANT_FALSE;
- exprval_t exprval;
+ jsval_t objv, namev;
+ IDispatch *obj;
+ jsstr_t *name;
+ BOOL ret;
HRESULT hres;
TRACE("\n");
- hres = expr_eval(ctx, expr->expression, EXPR_STRREF, ei, &exprval);
- if(FAILED(hres))
- return hres;
-
- switch(exprval.type) {
- case EXPRVAL_IDREF: {
- IDispatchEx *dispex;
+ namev = stack_pop(ctx);
+ objv = stack_pop(ctx);
- hres = IDispatch_QueryInterface(exprval.u.nameref.disp, &IID_IDispatchEx, (void**)&dispex);
- if(SUCCEEDED(hres)) {
- hres = IDispatchEx_DeleteMemberByDispID(dispex, exprval.u.idref.id);
- b = VARIANT_TRUE;
- IDispatchEx_Release(dispex);
- }
- break;
+ hres = to_object(ctx->script, objv, &obj);
+ jsval_release(objv);
+ if(FAILED(hres)) {
+ jsval_release(namev);
+ return hres;
}
- case EXPRVAL_NAMEREF: {
- IDispatchEx *dispex;
- hres = IDispatch_QueryInterface(exprval.u.nameref.disp, &IID_IDispatchEx, (void**)&dispex);
- if(SUCCEEDED(hres)) {
- hres = IDispatchEx_DeleteMemberByName(dispex, exprval.u.nameref.name,
- make_grfdex(ctx->parser->script, fdexNameCaseSensitive));
- b = VARIANT_TRUE;
- IDispatchEx_Release(dispex);
- }
- break;
- }
- default:
- FIXME("unsupported type %d\n", exprval.type);
- hres = E_NOTIMPL;
+ hres = to_string(ctx->script, namev, &name);
+ jsval_release(namev);
+ if(FAILED(hres)) {
+ IDispatch_Release(obj);
+ return hres;
}
- exprval_release(&exprval);
+ hres = disp_delete_name(ctx->script, obj, name, &ret);
+ IDispatch_Release(obj);
+ jsstr_release(name);
if(FAILED(hres))
return hres;
- return return_bool(ret, b);
+ return stack_push(ctx, jsval_bool(ret));
}
/* ECMA-262 3rd Edition 11.4.2 */
-HRESULT void_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
+static HRESULT interp_delete_ident(exec_ctx_t *ctx)
{
- unary_expression_t *expr = (unary_expression_t*)_expr;
+ const BSTR arg = get_op_bstr(ctx, 0);
exprval_t exprval;
- VARIANT tmp;
+ BOOL ret;
HRESULT hres;
- TRACE("\n");
+ TRACE("%s\n", debugstr_w(arg));
- hres = expr_eval(ctx, expr->expression, 0, ei, &exprval);
+ hres = identifier_eval(ctx->script, arg, &exprval);
if(FAILED(hres))
return hres;
- hres = exprval_to_value(ctx->parser->script, &exprval, ei, &tmp);
- exprval_release(&exprval);
- if(FAILED(hres))
- return hres;
+ switch(exprval.type) {
+ case EXPRVAL_IDREF:
+ hres = disp_delete(exprval.u.idref.disp, exprval.u.idref.id, &ret);
+ IDispatch_Release(exprval.u.idref.disp);
+ if(FAILED(hres))
+ return ret;
+ break;
+ case EXPRVAL_INVALID:
+ ret = TRUE;
+ break;
+ default:
+ FIXME("Unsupported exprval\n");
+ exprval_release(&exprval);
+ return E_NOTIMPL;
+ }
- VariantClear(&tmp);
- ret->type = EXPRVAL_VARIANT;
- V_VT(&ret->u.var) = VT_EMPTY;
- return S_OK;
+ return stack_push(ctx, jsval_bool(ret));
}
-/* ECMA-262 3rd Edition 11.4.3 */
-static HRESULT typeof_exprval(exec_ctx_t *ctx, exprval_t *exprval, jsexcept_t *ei, const WCHAR **ret)
+/* ECMA-262 3rd Edition 11.4.2 */
+static HRESULT interp_void(exec_ctx_t *ctx)
{
- VARIANT val;
- HRESULT hres;
-
- static const WCHAR booleanW[] = {'b','o','o','l','e','a','n',0};
- static const WCHAR functionW[] = {'f','u','n','c','t','i','o','n',0};
- static const WCHAR numberW[] = {'n','u','m','b','e','r',0};
- static const WCHAR objectW[] = {'o','b','j','e','c','t',0};
- static const WCHAR stringW[] = {'s','t','r','i','n','g',0};
- static const WCHAR undefinedW[] = {'u','n','d','e','f','i','n','e','d',0};
-
- if(exprval->type == EXPRVAL_INVALID) {
- *ret = undefinedW;
- return S_OK;
- }
+ TRACE("\n");
- hres = exprval_to_value(ctx->parser->script, exprval, ei, &val);
- if(FAILED(hres))
- return hres;
+ stack_popn(ctx, 1);
+ return stack_push(ctx, jsval_undefined());
+}
- switch(V_VT(&val)) {
- case VT_EMPTY:
+/* ECMA-262 3rd Edition 11.4.3 */
+static HRESULT typeof_string(jsval_t v, const WCHAR **ret)
+{
+ switch(jsval_type(v)) {
+ case JSV_UNDEFINED:
*ret = undefinedW;
break;
- case VT_NULL:
+ case JSV_NULL:
*ret = objectW;
break;
- case VT_BOOL:
- *ret = booleanW;
- break;
- case VT_I4:
- case VT_R8:
- *ret = numberW;
- break;
- case VT_BSTR:
- *ret = stringW;
- break;
- case VT_DISPATCH: {
- DispatchEx *dispex;
+ case JSV_OBJECT: {
+ jsdisp_t *dispex;
- if(V_DISPATCH(&val) && (dispex = iface_to_jsdisp((IUnknown*)V_DISPATCH(&val)))) {
+ if(get_object(v) && (dispex = iface_to_jsdisp((IUnknown*)get_object(v)))) {
*ret = is_class(dispex, JSCLASS_FUNCTION) ? functionW : objectW;
jsdisp_release(dispex);
}else {
}
break;
}
- default:
- FIXME("unhandled vt %d\n", V_VT(&val));
- hres = E_NOTIMPL;
- }
-
- VariantClear(&val);
- return S_OK;
-}
-
-HRESULT typeof_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
-{
- unary_expression_t *expr = (unary_expression_t*)_expr;
- const WCHAR *str = NULL;
- exprval_t exprval;
- HRESULT hres;
-
- TRACE("\n");
-
- hres = expr_eval(ctx, expr->expression, 0, ei, &exprval);
- if(FAILED(hres))
- return hres;
-
- hres = typeof_exprval(ctx, &exprval, ei, &str);
- exprval_release(&exprval);
- if(FAILED(hres))
- return hres;
-
- ret->type = EXPRVAL_VARIANT;
- V_VT(&ret->u.var) = VT_BSTR;
- V_BSTR(&ret->u.var) = SysAllocString(str);
- if(!V_BSTR(&ret->u.var))
- return E_OUTOFMEMORY;
+ case JSV_STRING:
+ *ret = stringW;
+ break;
+ case JSV_NUMBER:
+ *ret = numberW;
+ break;
+ case JSV_BOOL:
+ *ret = booleanW;
+ break;
+ case JSV_VARIANT:
+ FIXME("unhandled variant %s\n", debugstr_variant(get_variant(v)));
+ return E_NOTIMPL;
+ }
return S_OK;
}
-/* ECMA-262 3rd Edition 11.4.7 */
-HRESULT minus_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
+/* ECMA-262 3rd Edition 11.4.3 */
+static HRESULT interp_typeofid(exec_ctx_t *ctx)
{
- unary_expression_t *expr = (unary_expression_t*)_expr;
- exprval_t exprval;
- VARIANT val, num;
+ const WCHAR *ret;
+ IDispatch *obj;
+ jsval_t v;
+ DISPID id;
HRESULT hres;
TRACE("\n");
- hres = expr_eval(ctx, expr->expression, 0, ei, &exprval);
- if(FAILED(hres))
- return hres;
+ obj = stack_pop_objid(ctx, &id);
+ if(!obj)
+ return stack_push(ctx, jsval_string(jsstr_undefined()));
- hres = exprval_to_value(ctx->parser->script, &exprval, ei, &val);
- exprval_release(&exprval);
+ hres = disp_propget(ctx->script, obj, id, &v);
+ IDispatch_Release(obj);
if(FAILED(hres))
- return hres;
+ return stack_push_string(ctx, unknownW);
- hres = to_number(ctx->parser->script, &val, ei, &num);
- VariantClear(&val);
+ hres = typeof_string(v, &ret);
+ jsval_release(v);
if(FAILED(hres))
return hres;
- ret->type = EXPRVAL_VARIANT;
- num_set_val(&ret->u.var, -num_val(&num));
- return S_OK;
+ return stack_push_string(ctx, ret);
}
-/* ECMA-262 3rd Edition 11.4.6 */
-HRESULT plus_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
+/* ECMA-262 3rd Edition 11.4.3 */
+static HRESULT interp_typeofident(exec_ctx_t *ctx)
{
- unary_expression_t *expr = (unary_expression_t*)_expr;
+ const BSTR arg = get_op_bstr(ctx, 0);
exprval_t exprval;
- VARIANT val, num;
+ const WCHAR *ret;
+ jsval_t v;
HRESULT hres;
- TRACE("\n");
+ TRACE("%s\n", debugstr_w(arg));
- hres = expr_eval(ctx, expr->expression, EXPR_NEWREF, ei, &exprval);
+ hres = identifier_eval(ctx->script, arg, &exprval);
if(FAILED(hres))
return hres;
- hres = exprval_to_value(ctx->parser->script, &exprval, ei, &val);
+ if(exprval.type == EXPRVAL_INVALID) {
+ hres = stack_push(ctx, jsval_string(jsstr_undefined()));
+ exprval_release(&exprval);
+ return hres;
+ }
+
+ hres = exprval_to_value(ctx->script, &exprval, &v);
exprval_release(&exprval);
if(FAILED(hres))
return hres;
- hres = to_number(ctx->parser->script, &val, ei, &num);
- VariantClear(&val);
+ hres = typeof_string(v, &ret);
+ jsval_release(v);
if(FAILED(hres))
return hres;
- ret->type = EXPRVAL_VARIANT;
- ret->u.var = num;
- return S_OK;
+ return stack_push_string(ctx, ret);
}
-/* ECMA-262 3rd Edition 11.3.1 */
-HRESULT post_increment_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
+/* ECMA-262 3rd Edition 11.4.3 */
+static HRESULT interp_typeof(exec_ctx_t *ctx)
{
- unary_expression_t *expr = (unary_expression_t*)_expr;
- VARIANT val, num;
- exprval_t exprval;
+ const WCHAR *ret;
+ jsval_t v;
HRESULT hres;
TRACE("\n");
- hres = expr_eval(ctx, expr->expression, EXPR_NEWREF, ei, &exprval);
- if(FAILED(hres))
- return hres;
-
- hres = exprval_value(ctx->parser->script, &exprval, ei, &val);
- if(SUCCEEDED(hres)) {
- hres = to_number(ctx->parser->script, &val, ei, &num);
- VariantClear(&val);
- }
-
- if(SUCCEEDED(hres)) {
- VARIANT inc;
- num_set_val(&inc, num_val(&num)+1.0);
- hres = put_value(ctx->parser->script, &exprval, &inc, ei);
- }
-
- exprval_release(&exprval);
+ v = stack_pop(ctx);
+ hres = typeof_string(v, &ret);
+ jsval_release(v);
if(FAILED(hres))
return hres;
- ret->type = EXPRVAL_VARIANT;
- ret->u.var = num;
- return S_OK;
+ return stack_push_string(ctx, ret);
}
-/* ECMA-262 3rd Edition 11.3.2 */
-HRESULT post_decrement_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
+/* ECMA-262 3rd Edition 11.4.7 */
+static HRESULT interp_minus(exec_ctx_t *ctx)
{
- unary_expression_t *expr = (unary_expression_t*)_expr;
- VARIANT val, num;
- exprval_t exprval;
+ double n;
HRESULT hres;
TRACE("\n");
- hres = expr_eval(ctx, expr->expression, EXPR_NEWREF, ei, &exprval);
+ hres = stack_pop_number(ctx, &n);
if(FAILED(hres))
return hres;
- hres = exprval_value(ctx->parser->script, &exprval, ei, &val);
- if(SUCCEEDED(hres)) {
- hres = to_number(ctx->parser->script, &val, ei, &num);
- VariantClear(&val);
- }
+ return stack_push(ctx, jsval_number(-n));
+}
- if(SUCCEEDED(hres)) {
- VARIANT dec;
- num_set_val(&dec, num_val(&num)-1.0);
- hres = put_value(ctx->parser->script, &exprval, &dec, ei);
- }
+/* ECMA-262 3rd Edition 11.4.6 */
+static HRESULT interp_tonum(exec_ctx_t *ctx)
+{
+ jsval_t v;
+ double n;
+ HRESULT hres;
- exprval_release(&exprval);
+ TRACE("\n");
+
+ v = stack_pop(ctx);
+ hres = to_number(ctx->script, v, &n);
+ jsval_release(v);
if(FAILED(hres))
return hres;
- ret->type = EXPRVAL_VARIANT;
- ret->u.var = num;
- return S_OK;
+ return stack_push(ctx, jsval_number(n));
}
-/* ECMA-262 3rd Edition 11.4.4 */
-HRESULT pre_increment_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
+/* ECMA-262 3rd Edition 11.3.1 */
+static HRESULT interp_postinc(exec_ctx_t *ctx)
{
- unary_expression_t *expr = (unary_expression_t*)_expr;
- VARIANT val, num;
- exprval_t exprval;
+ const int arg = get_op_int(ctx, 0);
+ IDispatch *obj;
+ DISPID id;
+ jsval_t v;
HRESULT hres;
- TRACE("\n");
+ TRACE("%d\n", arg);
- hres = expr_eval(ctx, expr->expression, EXPR_NEWREF, ei, &exprval);
- if(FAILED(hres))
- return hres;
+ obj = stack_pop_objid(ctx, &id);
+ if(!obj)
+ return throw_type_error(ctx->script, JS_E_OBJECT_EXPECTED, NULL);
- hres = exprval_value(ctx->parser->script, &exprval, ei, &val);
+ hres = disp_propget(ctx->script, obj, id, &v);
if(SUCCEEDED(hres)) {
- hres = to_number(ctx->parser->script, &val, ei, &num);
- VariantClear(&val);
- }
+ double n;
- if(SUCCEEDED(hres)) {
- num_set_val(&val, num_val(&num)+1.0);
- hres = put_value(ctx->parser->script, &exprval, &val, ei);
+ hres = to_number(ctx->script, v, &n);
+ if(SUCCEEDED(hres))
+ hres = disp_propput(ctx->script, obj, id, jsval_number(n+(double)arg));
+ if(FAILED(hres))
+ jsval_release(v);
}
-
- exprval_release(&exprval);
+ IDispatch_Release(obj);
if(FAILED(hres))
return hres;
- ret->type = EXPRVAL_VARIANT;
- ret->u.var = val;
- return S_OK;
+ return stack_push(ctx, v);
}
-/* ECMA-262 3rd Edition 11.4.5 */
-HRESULT pre_decrement_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
+/* ECMA-262 3rd Edition 11.4.4, 11.4.5 */
+static HRESULT interp_preinc(exec_ctx_t *ctx)
{
- unary_expression_t *expr = (unary_expression_t*)_expr;
- VARIANT val, num;
- exprval_t exprval;
+ const int arg = get_op_int(ctx, 0);
+ IDispatch *obj;
+ double ret;
+ DISPID id;
+ jsval_t v;
HRESULT hres;
- TRACE("\n");
+ TRACE("%d\n", arg);
- hres = expr_eval(ctx, expr->expression, EXPR_NEWREF, ei, &exprval);
- if(FAILED(hres))
- return hres;
+ obj = stack_pop_objid(ctx, &id);
+ if(!obj)
+ return throw_type_error(ctx->script, JS_E_OBJECT_EXPECTED, NULL);
- hres = exprval_value(ctx->parser->script, &exprval, ei, &val);
+ hres = disp_propget(ctx->script, obj, id, &v);
if(SUCCEEDED(hres)) {
- hres = to_number(ctx->parser->script, &val, ei, &num);
- VariantClear(&val);
- }
+ double n;
- if(SUCCEEDED(hres)) {
- num_set_val(&val, num_val(&num)-1.0);
- hres = put_value(ctx->parser->script, &exprval, &val, ei);
+ hres = to_number(ctx->script, v, &n);
+ jsval_release(v);
+ if(SUCCEEDED(hres)) {
+ ret = n+(double)arg;
+ hres = disp_propput(ctx->script, obj, id, jsval_number(ret));
+ }
}
-
- exprval_release(&exprval);
+ IDispatch_Release(obj);
if(FAILED(hres))
return hres;
- ret->type = EXPRVAL_VARIANT;
- ret->u.var = val;
- return S_OK;
+ return stack_push(ctx, jsval_number(ret));
}
/* ECMA-262 3rd Edition 11.9.3 */
-static HRESULT equal_values(exec_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexcept_t *ei, BOOL *ret)
+static HRESULT equal_values(script_ctx_t *ctx, jsval_t lval, jsval_t rval, BOOL *ret)
{
- if(V_VT(lval) == V_VT(rval) || (is_num_vt(V_VT(lval)) && is_num_vt(V_VT(rval))))
+ if(jsval_type(lval) == jsval_type(rval) || (is_number(lval) && is_number(rval)))
return equal2_values(lval, rval, ret);
/* FIXME: NULL disps should be handled in more general way */
- if(V_VT(lval) == VT_DISPATCH && !V_DISPATCH(lval)) {
- VARIANT v;
- V_VT(&v) = VT_NULL;
- return equal_values(ctx, &v, rval, ei, ret);
- }
-
- if(V_VT(rval) == VT_DISPATCH && !V_DISPATCH(rval)) {
- VARIANT v;
- V_VT(&v) = VT_NULL;
- return equal_values(ctx, lval, &v, ei, ret);
- }
+ if(is_object_instance(lval) && !get_object(lval))
+ return equal_values(ctx, jsval_null(), rval, ret);
+ if(is_object_instance(rval) && !get_object(rval))
+ return equal_values(ctx, lval, jsval_null(), ret);
- if((V_VT(lval) == VT_NULL && V_VT(rval) == VT_EMPTY) ||
- (V_VT(lval) == VT_EMPTY && V_VT(rval) == VT_NULL)) {
+ if((is_null(lval) && is_undefined(rval)) || (is_undefined(lval) && is_null(rval))) {
*ret = TRUE;
return S_OK;
}
- if(V_VT(lval) == VT_BSTR && is_num_vt(V_VT(rval))) {
- VARIANT v;
+ if(is_string(lval) && is_number(rval)) {
+ double n;
HRESULT hres;
- hres = to_number(ctx->parser->script, lval, ei, &v);
+ hres = to_number(ctx, lval, &n);
if(FAILED(hres))
return hres;
- return equal_values(ctx, &v, rval, ei, ret);
+ /* FIXME: optimize */
+ return equal_values(ctx, jsval_number(n), rval, ret);
}
- if(V_VT(rval) == VT_BSTR && is_num_vt(V_VT(lval))) {
- VARIANT v;
+ if(is_string(rval) && is_number(lval)) {
+ double n;
HRESULT hres;
- hres = to_number(ctx->parser->script, rval, ei, &v);
+ hres = to_number(ctx, rval, &n);
if(FAILED(hres))
return hres;
- return equal_values(ctx, lval, &v, ei, ret);
- }
-
- if(V_VT(rval) == VT_BOOL) {
- VARIANT v;
-
- V_VT(&v) = VT_I4;
- V_I4(&v) = V_BOOL(rval) ? 1 : 0;
- return equal_values(ctx, lval, &v, ei, ret);
+ /* FIXME: optimize */
+ return equal_values(ctx, lval, jsval_number(n), ret);
}
- if(V_VT(lval) == VT_BOOL) {
- VARIANT v;
+ if(is_bool(rval))
+ return equal_values(ctx, lval, jsval_number(get_bool(rval) ? 1 : 0), ret);
- V_VT(&v) = VT_I4;
- V_I4(&v) = V_BOOL(lval) ? 1 : 0;
- return equal_values(ctx, &v, rval, ei, ret);
- }
+ if(is_bool(lval))
+ return equal_values(ctx, jsval_number(get_bool(lval) ? 1 : 0), rval, ret);
- if(V_VT(rval) == VT_DISPATCH && (V_VT(lval) == VT_BSTR || is_num_vt(V_VT(lval)))) {
- VARIANT v;
+ if(is_object_instance(rval) && (is_string(lval) || is_number(lval))) {
+ jsval_t prim;
HRESULT hres;
- hres = to_primitive(ctx->parser->script, rval, ei, &v, NO_HINT);
+ hres = to_primitive(ctx, rval, &prim, NO_HINT);
if(FAILED(hres))
return hres;
- hres = equal_values(ctx, lval, &v, ei, ret);
-
- VariantClear(&v);
+ hres = equal_values(ctx, lval, prim, ret);
+ jsval_release(prim);
return hres;
}
- if(V_VT(lval) == VT_DISPATCH && (V_VT(rval) == VT_BSTR || is_num_vt(V_VT(rval)))) {
- VARIANT v;
+ if(is_object_instance(lval) && (is_string(rval) || is_number(rval))) {
+ jsval_t prim;
HRESULT hres;
- hres = to_primitive(ctx->parser->script, lval, ei, &v, NO_HINT);
+ hres = to_primitive(ctx, lval, &prim, NO_HINT);
if(FAILED(hres))
return hres;
- hres = equal_values(ctx, &v, rval, ei, ret);
-
- VariantClear(&v);
+ hres = equal_values(ctx, prim, rval, ret);
+ jsval_release(prim);
return hres;
}
}
/* ECMA-262 3rd Edition 11.9.1 */
-HRESULT equal_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
+static HRESULT interp_eq(exec_ctx_t *ctx)
{
- binary_expression_t *expr = (binary_expression_t*)_expr;
- VARIANT rval, lval;
+ jsval_t l, r;
BOOL b;
HRESULT hres;
- TRACE("\n");
+ r = stack_pop(ctx);
+ l = stack_pop(ctx);
- hres = get_binary_expr_values(ctx, expr, ei, &rval, &lval);
- if(FAILED(hres))
- return hres;
+ TRACE("%s == %s\n", debugstr_jsval(l), debugstr_jsval(r));
- hres = equal_values(ctx, &rval, &lval, ei, &b);
- VariantClear(&lval);
- VariantClear(&rval);
+ hres = equal_values(ctx->script, l, r, &b);
+ jsval_release(l);
+ jsval_release(r);
if(FAILED(hres))
return hres;
- return return_bool(ret, b);
+ return stack_push(ctx, jsval_bool(b));
}
-/* ECMA-262 3rd Edition 11.9.4 */
-HRESULT equal2_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
+/* ECMA-262 3rd Edition 11.9.2 */
+static HRESULT interp_neq(exec_ctx_t *ctx)
{
- binary_expression_t *expr = (binary_expression_t*)_expr;
- VARIANT rval, lval;
+ jsval_t l, r;
BOOL b;
HRESULT hres;
- TRACE("\n");
+ r = stack_pop(ctx);
+ l = stack_pop(ctx);
- hres = get_binary_expr_values(ctx, expr, ei, &rval, &lval);
- if(FAILED(hres))
- return hres;
+ TRACE("%s != %s\n", debugstr_jsval(l), debugstr_jsval(r));
- hres = equal2_values(&rval, &lval, &b);
- VariantClear(&lval);
- VariantClear(&rval);
+ hres = equal_values(ctx->script, l, r, &b);
+ jsval_release(l);
+ jsval_release(r);
if(FAILED(hres))
return hres;
- return return_bool(ret, b);
+ return stack_push(ctx, jsval_bool(!b));
}
-/* ECMA-262 3rd Edition 11.9.2 */
-HRESULT not_equal_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
+/* ECMA-262 3rd Edition 11.9.4 */
+static HRESULT interp_eq2(exec_ctx_t *ctx)
{
- binary_expression_t *expr = (binary_expression_t*)_expr;
- VARIANT rval, lval;
+ jsval_t l, r;
BOOL b;
HRESULT hres;
TRACE("\n");
- hres = get_binary_expr_values(ctx, expr, ei, &lval, &rval);
- if(FAILED(hres))
- return hres;
+ r = stack_pop(ctx);
+ l = stack_pop(ctx);
- hres = equal_values(ctx, &lval, &rval, ei, &b);
- VariantClear(&lval);
- VariantClear(&rval);
+ hres = equal2_values(r, l, &b);
+ jsval_release(l);
+ jsval_release(r);
if(FAILED(hres))
return hres;
- return return_bool(ret, !b);
+ return stack_push(ctx, jsval_bool(b));
}
/* ECMA-262 3rd Edition 11.9.5 */
-HRESULT not_equal2_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
+static HRESULT interp_neq2(exec_ctx_t *ctx)
{
- binary_expression_t *expr = (binary_expression_t*)_expr;
- VARIANT rval, lval;
+ jsval_t l, r;
BOOL b;
HRESULT hres;
TRACE("\n");
- hres = get_binary_expr_values(ctx, expr, ei, &lval, &rval);
- if(FAILED(hres))
- return hres;
+ r = stack_pop(ctx);
+ l = stack_pop(ctx);
- hres = equal2_values(&lval, &rval, &b);
- VariantClear(&lval);
- VariantClear(&rval);
+ hres = equal2_values(r, l, &b);
+ jsval_release(l);
+ jsval_release(r);
if(FAILED(hres))
return hres;
- return return_bool(ret, !b);
+ return stack_push(ctx, jsval_bool(!b));
}
/* ECMA-262 3rd Edition 11.8.5 */
-static HRESULT less_eval(exec_ctx_t *ctx, VARIANT *lval, VARIANT *rval, BOOL greater, jsexcept_t *ei, BOOL *ret)
+static HRESULT less_eval(script_ctx_t *ctx, jsval_t lval, jsval_t rval, BOOL greater, BOOL *ret)
{
- VARIANT l, r, ln, rn;
+ double ln, rn;
+ jsval_t l, r;
HRESULT hres;
- hres = to_primitive(ctx->parser->script, lval, ei, &l, NO_HINT);
+ hres = to_primitive(ctx, lval, &l, NO_HINT);
if(FAILED(hres))
return hres;
- hres = to_primitive(ctx->parser->script, rval, ei, &r, NO_HINT);
+ hres = to_primitive(ctx, rval, &r, NO_HINT);
if(FAILED(hres)) {
- VariantClear(&l);
+ jsval_release(l);
return hres;
}
- if(V_VT(&l) == VT_BSTR && V_VT(&r) == VT_BSTR) {
- *ret = (strcmpW(V_BSTR(&l), V_BSTR(&r)) < 0) ^ greater;
- SysFreeString(V_BSTR(&l));
- SysFreeString(V_BSTR(&r));
+ if(is_string(l) && is_string(r)) {
+ *ret = (jsstr_cmp(get_string(l), get_string(r)) < 0) ^ greater;
+ jsstr_release(get_string(l));
+ jsstr_release(get_string(r));
return S_OK;
}
- hres = to_number(ctx->parser->script, &l, ei, &ln);
- VariantClear(&l);
+ hres = to_number(ctx, l, &ln);
+ jsval_release(l);
if(SUCCEEDED(hres))
- hres = to_number(ctx->parser->script, &r, ei, &rn);
- VariantClear(&r);
+ hres = to_number(ctx, r, &rn);
+ jsval_release(r);
if(FAILED(hres))
return hres;
- if(V_VT(&ln) == VT_I4 && V_VT(&rn) == VT_I4) {
- *ret = (V_I4(&ln) < V_I4(&rn)) ^ greater;
- }else {
- DOUBLE ld = num_val(&ln);
- DOUBLE rd = num_val(&rn);
-
- *ret = !isnan(ld) && !isnan(rd) && ((ld < rd) ^ greater);
- }
-
+ *ret = !isnan(ln) && !isnan(rn) && ((ln < rn) ^ greater);
return S_OK;
}
/* ECMA-262 3rd Edition 11.8.1 */
-HRESULT less_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
+static HRESULT interp_lt(exec_ctx_t *ctx)
{
- binary_expression_t *expr = (binary_expression_t*)_expr;
- VARIANT rval, lval;
+ jsval_t l, r;
BOOL b;
HRESULT hres;
- TRACE("\n");
+ r = stack_pop(ctx);
+ l = stack_pop(ctx);
- hres = get_binary_expr_values(ctx, expr, ei, &lval, &rval);
- if(FAILED(hres))
- return hres;
+ TRACE("%s < %s\n", debugstr_jsval(l), debugstr_jsval(r));
- hres = less_eval(ctx, &lval, &rval, FALSE, ei, &b);
- VariantClear(&lval);
- VariantClear(&rval);
+ hres = less_eval(ctx->script, l, r, FALSE, &b);
+ jsval_release(l);
+ jsval_release(r);
if(FAILED(hres))
return hres;
- return return_bool(ret, b);
+ return stack_push(ctx, jsval_bool(b));
}
-/* ECMA-262 3rd Edition 11.8.3 */
-HRESULT lesseq_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
+/* ECMA-262 3rd Edition 11.8.1 */
+static HRESULT interp_lteq(exec_ctx_t *ctx)
{
- binary_expression_t *expr = (binary_expression_t*)_expr;
- VARIANT rval, lval;
+ jsval_t l, r;
BOOL b;
HRESULT hres;
- TRACE("\n");
+ r = stack_pop(ctx);
+ l = stack_pop(ctx);
- hres = get_binary_expr_values(ctx, expr, ei, &lval, &rval);
- if(FAILED(hres))
- return hres;
+ TRACE("%s <= %s\n", debugstr_jsval(l), debugstr_jsval(r));
- hres = less_eval(ctx, &rval, &lval, TRUE, ei, &b);
- VariantClear(&lval);
- VariantClear(&rval);
+ hres = less_eval(ctx->script, r, l, TRUE, &b);
+ jsval_release(l);
+ jsval_release(r);
if(FAILED(hres))
return hres;
- return return_bool(ret, b);
+ return stack_push(ctx, jsval_bool(b));
}
/* ECMA-262 3rd Edition 11.8.2 */
-HRESULT greater_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
+static HRESULT interp_gt(exec_ctx_t *ctx)
{
- binary_expression_t *expr = (binary_expression_t*)_expr;
- VARIANT rval, lval;
+ jsval_t l, r;
BOOL b;
HRESULT hres;
- TRACE("\n");
+ r = stack_pop(ctx);
+ l = stack_pop(ctx);
- hres = get_binary_expr_values(ctx, expr, ei, &lval, &rval);
- if(FAILED(hres))
- return hres;
+ TRACE("%s > %s\n", debugstr_jsval(l), debugstr_jsval(r));
- hres = less_eval(ctx, &rval, &lval, FALSE, ei, &b);
- VariantClear(&lval);
- VariantClear(&rval);
+ hres = less_eval(ctx->script, r, l, FALSE, &b);
+ jsval_release(l);
+ jsval_release(r);
if(FAILED(hres))
return hres;
- return return_bool(ret, b);
+ return stack_push(ctx, jsval_bool(b));
}
/* ECMA-262 3rd Edition 11.8.4 */
-HRESULT greatereq_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
+static HRESULT interp_gteq(exec_ctx_t *ctx)
{
- binary_expression_t *expr = (binary_expression_t*)_expr;
- VARIANT rval, lval;
+ jsval_t l, r;
BOOL b;
HRESULT hres;
- TRACE("\n");
+ r = stack_pop(ctx);
+ l = stack_pop(ctx);
- hres = get_binary_expr_values(ctx, expr, ei, &lval, &rval);
- if(FAILED(hres))
- return hres;
+ TRACE("%s >= %s\n", debugstr_jsval(l), debugstr_jsval(r));
- hres = less_eval(ctx, &lval, &rval, TRUE, ei, &b);
- VariantClear(&lval);
- VariantClear(&rval);
+ hres = less_eval(ctx->script, l, r, TRUE, &b);
+ jsval_release(l);
+ jsval_release(r);
if(FAILED(hres))
return hres;
- return return_bool(ret, b);
+ return stack_push(ctx, jsval_bool(b));
}
/* ECMA-262 3rd Edition 11.4.8 */
-HRESULT binary_negation_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
+static HRESULT interp_bneg(exec_ctx_t *ctx)
{
- unary_expression_t *expr = (unary_expression_t*)_expr;
- exprval_t exprval;
- VARIANT val;
+ jsval_t v;
INT i;
HRESULT hres;
TRACE("\n");
- hres = expr_eval(ctx, expr->expression, EXPR_NEWREF, ei, &exprval);
- if(FAILED(hres))
- return hres;
-
- hres = exprval_to_value(ctx->parser->script, &exprval, ei, &val);
- exprval_release(&exprval);
- if(FAILED(hres))
- return hres;
-
- hres = to_int32(ctx->parser->script, &val, ei, &i);
+ v = stack_pop(ctx);
+ hres = to_int32(ctx->script, v, &i);
+ jsval_release(v);
if(FAILED(hres))
return hres;
- ret->type = EXPRVAL_VARIANT;
- V_VT(&ret->u.var) = VT_I4;
- V_I4(&ret->u.var) = ~i;
- return S_OK;
+ return stack_push(ctx, jsval_number(~i));
}
/* ECMA-262 3rd Edition 11.4.9 */
-HRESULT logical_negation_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
+static HRESULT interp_neg(exec_ctx_t *ctx)
{
- unary_expression_t *expr = (unary_expression_t*)_expr;
- exprval_t exprval;
- VARIANT_BOOL b;
+ jsval_t v;
+ BOOL b;
HRESULT hres;
TRACE("\n");
- hres = expr_eval(ctx, expr->expression, EXPR_NEWREF, ei, &exprval);
- if(FAILED(hres))
- return hres;
-
- hres = exprval_to_boolean(ctx->parser->script, &exprval, ei, &b);
- exprval_release(&exprval);
+ v = stack_pop(ctx);
+ hres = to_boolean(v, &b);
+ jsval_release(v);
if(FAILED(hres))
return hres;
- return return_bool(ret, !b);
+ return stack_push(ctx, jsval_bool(!b));
}
/* ECMA-262 3rd Edition 11.7.1 */
-static HRESULT lshift_eval(exec_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexcept_t *ei, VARIANT *retv)
+static HRESULT interp_lshift(exec_ctx_t *ctx)
{
- DWORD ri;
- INT li;
+ DWORD r;
+ INT l;
HRESULT hres;
- hres = to_int32(ctx->parser->script, lval, ei, &li);
+ hres = stack_pop_uint(ctx, &r);
if(FAILED(hres))
return hres;
- hres = to_uint32(ctx->parser->script, rval, ei, &ri);
+ hres = stack_pop_int(ctx, &l);
if(FAILED(hres))
return hres;
- V_VT(retv) = VT_I4;
- V_I4(retv) = li << (ri&0x1f);
- return S_OK;
+ return stack_push(ctx, jsval_number(l << (r&0x1f)));
}
-/* ECMA-262 3rd Edition 11.7.1 */
-HRESULT left_shift_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
+/* ECMA-262 3rd Edition 11.7.2 */
+static HRESULT interp_rshift(exec_ctx_t *ctx)
{
- binary_expression_t *expr = (binary_expression_t*)_expr;
+ DWORD r;
+ INT l;
+ HRESULT hres;
- TRACE("\n");
+ hres = stack_pop_uint(ctx, &r);
+ if(FAILED(hres))
+ return hres;
+
+ hres = stack_pop_int(ctx, &l);
+ if(FAILED(hres))
+ return hres;
- return binary_expr_eval(ctx, expr, lshift_eval, ei, ret);
+ return stack_push(ctx, jsval_number(l >> (r&0x1f)));
}
-/* ECMA-262 3rd Edition 11.7.2 */
-static HRESULT rshift_eval(exec_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexcept_t *ei, VARIANT *retv)
+/* ECMA-262 3rd Edition 11.7.3 */
+static HRESULT interp_rshift2(exec_ctx_t *ctx)
{
- DWORD ri;
- INT li;
+ DWORD r, l;
HRESULT hres;
- hres = to_int32(ctx->parser->script, lval, ei, &li);
+ hres = stack_pop_uint(ctx, &r);
if(FAILED(hres))
return hres;
- hres = to_uint32(ctx->parser->script, rval, ei, &ri);
+ hres = stack_pop_uint(ctx, &l);
if(FAILED(hres))
return hres;
- V_VT(retv) = VT_I4;
- V_I4(retv) = li >> (ri&0x1f);
- return S_OK;
+ return stack_push(ctx, jsval_number(l >> (r&0x1f)));
}
-/* ECMA-262 3rd Edition 11.7.2 */
-HRESULT right_shift_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
+/* ECMA-262 3rd Edition 11.13.1 */
+static HRESULT interp_assign(exec_ctx_t *ctx)
{
- binary_expression_t *expr = (binary_expression_t*)_expr;
+ IDispatch *disp;
+ DISPID id;
+ jsval_t v;
+ HRESULT hres;
TRACE("\n");
- return binary_expr_eval(ctx, expr, rshift_eval, ei, ret);
+ v = stack_pop(ctx);
+
+ disp = stack_pop_objid(ctx, &id);
+ if(!disp) {
+ jsval_release(v);
+ return throw_reference_error(ctx->script, JS_E_ILLEGAL_ASSIGN, NULL);
+ }
+
+ hres = disp_propput(ctx->script, disp, id, v);
+ IDispatch_Release(disp);
+ if(FAILED(hres)) {
+ jsval_release(v);
+ return hres;
+ }
+
+ return stack_push(ctx, v);
}
-/* ECMA-262 3rd Edition 11.7.3 */
-static HRESULT rshift2_eval(exec_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexcept_t *ei, VARIANT *retv)
+/* JScript extension */
+static HRESULT interp_assign_call(exec_ctx_t *ctx)
{
- DWORD li, ri;
+ const unsigned argc = get_op_uint(ctx, 0);
+ IDispatch *disp;
+ jsval_t v;
+ DISPID id;
HRESULT hres;
- hres = to_uint32(ctx->parser->script, lval, ei, &li);
- if(FAILED(hres))
- return hres;
+ TRACE("%u\n", argc);
+
+ disp = stack_topn_objid(ctx, argc+1, &id);
+ if(!disp)
+ return throw_reference_error(ctx->script, JS_E_ILLEGAL_ASSIGN, NULL);
- hres = to_uint32(ctx->parser->script, rval, ei, &ri);
+ hres = disp_call(ctx->script, disp, id, DISPATCH_PROPERTYPUT, argc+1, stack_args(ctx, argc+1), NULL);
if(FAILED(hres))
return hres;
- V_VT(retv) = VT_I4;
- V_I4(retv) = li >> (ri&0x1f);
- return S_OK;
+ v = stack_pop(ctx);
+ stack_popn(ctx, argc+2);
+ return stack_push(ctx, v);
}
-/* ECMA-262 3rd Edition 11.7.3 */
-HRESULT right2_shift_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
+static HRESULT interp_undefined(exec_ctx_t *ctx)
{
- binary_expression_t *expr = (binary_expression_t*)_expr;
-
TRACE("\n");
- return binary_expr_eval(ctx, expr, rshift2_eval, ei, ret);
+ return stack_push(ctx, jsval_undefined());
}
-/* ECMA-262 3rd Edition 11.13.1 */
-HRESULT assign_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
+static HRESULT interp_jmp(exec_ctx_t *ctx)
{
- binary_expression_t *expr = (binary_expression_t*)_expr;
- exprval_t exprval, exprvalr;
- VARIANT rval;
- HRESULT hres;
+ const unsigned arg = get_op_uint(ctx, 0);
- TRACE("\n");
+ TRACE("%u\n", arg);
- hres = expr_eval(ctx, expr->expression1, EXPR_NEWREF, ei, &exprval);
- if(FAILED(hres))
- return hres;
+ ctx->ip = arg;
+ return S_OK;
+}
- hres = expr_eval(ctx, expr->expression2, 0, ei, &exprvalr);
- if(SUCCEEDED(hres)) {
- hres = exprval_to_value(ctx->parser->script, &exprvalr, ei, &rval);
- exprval_release(&exprvalr);
- }
+static HRESULT interp_jmp_z(exec_ctx_t *ctx)
+{
+ const unsigned arg = get_op_uint(ctx, 0);
+ BOOL b;
+ jsval_t v;
+ HRESULT hres;
- if(SUCCEEDED(hres)) {
- hres = put_value(ctx->parser->script, &exprval, &rval, ei);
- if(FAILED(hres))
- VariantClear(&rval);
- }
+ TRACE("\n");
- exprval_release(&exprval);
+ v = stack_pop(ctx);
+ hres = to_boolean(v, &b);
+ jsval_release(v);
if(FAILED(hres))
return hres;
- ret->type = EXPRVAL_VARIANT;
- ret->u.var = rval;
+ if(b)
+ ctx->ip++;
+ else
+ ctx->ip = arg;
return S_OK;
}
-/* ECMA-262 3rd Edition 11.13.2 */
-HRESULT assign_lshift_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
+static HRESULT interp_pop(exec_ctx_t *ctx)
{
- binary_expression_t *expr = (binary_expression_t*)_expr;
+ const unsigned arg = get_op_uint(ctx, 0);
- TRACE("\n");
+ TRACE("%u\n", arg);
- return assign_oper_eval(ctx, expr->expression1, expr->expression2, lshift_eval, ei, ret);
+ stack_popn(ctx, arg);
+ return S_OK;
}
-/* ECMA-262 3rd Edition 11.13.2 */
-HRESULT assign_rshift_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
+static HRESULT interp_ret(exec_ctx_t *ctx)
{
- binary_expression_t *expr = (binary_expression_t*)_expr;
-
TRACE("\n");
- return assign_oper_eval(ctx, expr->expression1, expr->expression2, rshift_eval, ei, ret);
+ ctx->ip = -1;
+ return S_OK;
}
-/* ECMA-262 3rd Edition 11.13.2 */
-HRESULT assign_rrshift_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
+static HRESULT interp_setret(exec_ctx_t *ctx)
{
- binary_expression_t *expr = (binary_expression_t*)_expr;
-
TRACE("\n");
- return assign_oper_eval(ctx, expr->expression1, expr->expression2, rshift2_eval, ei, ret);
+ jsval_release(ctx->ret);
+ ctx->ret = stack_pop(ctx);
+ return S_OK;
}
-/* ECMA-262 3rd Edition 11.13.2 */
-HRESULT assign_add_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
-{
- binary_expression_t *expr = (binary_expression_t*)_expr;
+typedef HRESULT (*op_func_t)(exec_ctx_t*);
- TRACE("\n");
+static const op_func_t op_funcs[] = {
+#define X(x,a,b,c) interp_##x,
+OP_LIST
+#undef X
+};
- return assign_oper_eval(ctx, expr->expression1, expr->expression2, add_eval, ei, ret);
-}
+static const unsigned op_move[] = {
+#define X(a,x,b,c) x,
+OP_LIST
+#undef X
+};
-/* ECMA-262 3rd Edition 11.13.2 */
-HRESULT assign_sub_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
+static HRESULT unwind_exception(exec_ctx_t *ctx)
{
- binary_expression_t *expr = (binary_expression_t*)_expr;
+ except_frame_t *except_frame;
+ jsval_t except_val;
+ BSTR ident;
+ HRESULT hres;
- TRACE("\n");
+ except_frame = ctx->except_frame;
+ ctx->except_frame = except_frame->next;
- return assign_oper_eval(ctx, expr->expression1, expr->expression2, sub_eval, ei, ret);
-}
+ assert(except_frame->stack_top <= ctx->top);
+ stack_popn(ctx, ctx->top - except_frame->stack_top);
-/* ECMA-262 3rd Edition 11.13.2 */
-HRESULT assign_mul_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
-{
- binary_expression_t *expr = (binary_expression_t*)_expr;
+ while(except_frame->scope != ctx->scope_chain)
+ scope_pop(&ctx->scope_chain);
- TRACE("\n");
+ ctx->ip = except_frame->catch_off;
- return assign_oper_eval(ctx, expr->expression1, expr->expression2, mul_eval, ei, ret);
-}
+ except_val = ctx->script->ei.val;
+ ctx->script->ei.val = jsval_undefined();
+ clear_ei(ctx->script);
-/* ECMA-262 3rd Edition 11.13.2 */
-HRESULT assign_div_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
-{
- binary_expression_t *expr = (binary_expression_t*)_expr;
+ ident = except_frame->ident;
+ heap_free(except_frame);
- TRACE("\n");
+ if(ident) {
+ jsdisp_t *scope_obj;
- return assign_oper_eval(ctx, expr->expression1, expr->expression2, div_eval, ei, ret);
-}
+ hres = create_dispex(ctx->script, NULL, NULL, &scope_obj);
+ if(SUCCEEDED(hres)) {
+ hres = jsdisp_propput_name(scope_obj, ident, except_val);
+ if(FAILED(hres))
+ jsdisp_release(scope_obj);
+ }
+ jsval_release(except_val);
+ if(FAILED(hres))
+ return hres;
-/* ECMA-262 3rd Edition 11.13.2 */
-HRESULT assign_mod_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
-{
- binary_expression_t *expr = (binary_expression_t*)_expr;
+ hres = scope_push(ctx->scope_chain, scope_obj, to_disp(scope_obj), &ctx->scope_chain);
+ jsdisp_release(scope_obj);
+ }else {
+ hres = stack_push(ctx, except_val);
+ if(FAILED(hres))
+ return hres;
- TRACE("\n");
+ hres = stack_push(ctx, jsval_bool(FALSE));
+ }
- return assign_oper_eval(ctx, expr->expression1, expr->expression2, mod_eval, ei, ret);
+ return hres;
}
-/* ECMA-262 3rd Edition 11.13.2 */
-HRESULT assign_and_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
+static HRESULT enter_bytecode(script_ctx_t *ctx, bytecode_t *code, function_code_t *func, jsval_t *ret)
{
- binary_expression_t *expr = (binary_expression_t*)_expr;
+ exec_ctx_t *exec_ctx = ctx->exec_ctx;
+ except_frame_t *prev_except_frame;
+ function_code_t *prev_func;
+ unsigned prev_ip, prev_top;
+ scope_chain_t *prev_scope;
+ bytecode_t *prev_code;
+ jsop_t op;
+ HRESULT hres = S_OK;
TRACE("\n");
- return assign_oper_eval(ctx, expr->expression1, expr->expression2, bitand_eval, ei, ret);
-}
+ prev_top = exec_ctx->top;
+ prev_scope = exec_ctx->scope_chain;
+ prev_except_frame = exec_ctx->except_frame;
+ prev_ip = exec_ctx->ip;
+ prev_code = exec_ctx->code;
+ prev_func = exec_ctx->func_code;
+ exec_ctx->ip = func->instr_off;
+ exec_ctx->except_frame = NULL;
+ exec_ctx->code = code;
+ exec_ctx->func_code = func;
-/* ECMA-262 3rd Edition 11.13.2 */
-HRESULT assign_or_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
-{
- binary_expression_t *expr = (binary_expression_t*)_expr;
+ while(exec_ctx->ip != -1) {
+ op = code->instrs[exec_ctx->ip].op;
+ hres = op_funcs[op](exec_ctx);
+ if(FAILED(hres)) {
+ TRACE("EXCEPTION %08x\n", hres);
- TRACE("\n");
+ if(!exec_ctx->except_frame)
+ break;
+
+ hres = unwind_exception(exec_ctx);
+ if(FAILED(hres))
+ break;
+ }else {
+ exec_ctx->ip += op_move[op];
+ }
+ }
+
+ exec_ctx->ip = prev_ip;
+ exec_ctx->except_frame = prev_except_frame;
+ exec_ctx->code = prev_code;
+ exec_ctx->func_code = prev_func;
+
+ if(FAILED(hres)) {
+ while(exec_ctx->scope_chain != prev_scope)
+ scope_pop(&exec_ctx->scope_chain);
+ stack_popn(exec_ctx, exec_ctx->top-prev_top);
+ return hres;
+ }
- return assign_oper_eval(ctx, expr->expression1, expr->expression2, bitor_eval, ei, ret);
+ assert(exec_ctx->top == prev_top+1 || exec_ctx->top == prev_top);
+ assert(exec_ctx->scope_chain == prev_scope);
+ assert(exec_ctx->top == prev_top);
+
+ *ret = exec_ctx->ret;
+ exec_ctx->ret = jsval_undefined();
+ return S_OK;
}
-/* ECMA-262 3rd Edition 11.13.2 */
-HRESULT assign_xor_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
+HRESULT exec_source(exec_ctx_t *ctx, bytecode_t *code, function_code_t *func, BOOL from_eval, jsval_t *ret)
{
- binary_expression_t *expr = (binary_expression_t*)_expr;
+ exec_ctx_t *prev_ctx;
+ jsval_t val;
+ unsigned i;
+ HRESULT hres = S_OK;
- TRACE("\n");
+ for(i = 0; i < func->func_cnt; i++) {
+ jsdisp_t *func_obj;
+
+ if(!func->funcs[i].name)
+ continue;
+
+ hres = create_source_function(ctx->script, code, func->funcs+i, ctx->scope_chain, &func_obj);
+ if(FAILED(hres))
+ return hres;
- return assign_oper_eval(ctx, expr->expression1, expr->expression2, xor_eval, ei, ret);
+ hres = jsdisp_propput_name(ctx->var_disp, func->funcs[i].name, jsval_obj(func_obj));
+ jsdisp_release(func_obj);
+ if(FAILED(hres))
+ return hres;
+ }
+
+ for(i=0; i < func->var_cnt; i++) {
+ if(!ctx->is_global || !lookup_global_members(ctx->script, func->variables[i], NULL)) {
+ DISPID id = 0;
+
+ hres = jsdisp_get_id(ctx->var_disp, func->variables[i], fdexNameEnsure, &id);
+ if(FAILED(hres))
+ return hres;
+ }
+ }
+
+ prev_ctx = ctx->script->exec_ctx;
+ ctx->script->exec_ctx = ctx;
+
+ hres = enter_bytecode(ctx->script, code, func, &val);
+ assert(ctx->script->exec_ctx == ctx);
+ ctx->script->exec_ctx = prev_ctx;
+ if(FAILED(hres))
+ return hres;
+
+ if(ret)
+ *ret = val;
+ else
+ jsval_release(val);
+ return S_OK;
}
/*
- * Copyright 2008 Jacek Caban for CodeWeavers
+ * Copyright 2008,2011 Jacek Caban for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
*/
typedef struct _source_elements_t source_elements_t;
-typedef struct _function_expression_t function_expression_t;
-
-typedef struct _function_declaration_t {
- function_expression_t *expr;
-
- struct _function_declaration_t *next;
-} function_declaration_t;
-
-typedef struct _var_list_t {
- const WCHAR *identifier;
-
- struct _var_list_t *next;
-} var_list_t;
-
-typedef struct _func_stack {
- function_declaration_t *func_head;
- function_declaration_t *func_tail;
- var_list_t *var_head;
- var_list_t *var_tail;
-
- struct _func_stack *next;
-} func_stack_t;
-
-typedef struct _parser_ctx_t {
- LONG ref;
+typedef struct _expression_t expression_t;
+typedef struct _statement_t statement_t;
- WCHAR *begin;
+typedef struct {
+ const WCHAR *begin;
const WCHAR *end;
const WCHAR *ptr;
script_ctx_t *script;
source_elements_t *source;
BOOL nl;
+ BOOL implicit_nl_semicolon;
BOOL is_html;
BOOL lexer_error;
HRESULT hres;
- jsheap_t heap;
+ heap_pool_t heap;
+} parser_ctx_t;
- func_stack_t *func_stack;
+#define OP_LIST \
+ X(add, 1, 0,0) \
+ X(and, 1, 0,0) \
+ X(array, 1, 0,0) \
+ X(assign, 1, 0,0) \
+ X(assign_call,1, ARG_UINT, 0) \
+ X(bool, 1, ARG_INT, 0) \
+ X(bneg, 1, 0,0) \
+ X(call, 1, ARG_UINT, ARG_UINT) \
+ X(call_member,1, ARG_UINT, ARG_UINT) \
+ X(carray, 1, ARG_UINT, 0) \
+ X(case, 0, ARG_ADDR, 0) \
+ X(cnd_nz, 0, ARG_ADDR, 0) \
+ X(cnd_z, 0, ARG_ADDR, 0) \
+ X(delete, 1, 0,0) \
+ X(delete_ident,1,ARG_BSTR, 0) \
+ X(div, 1, 0,0) \
+ X(double, 1, ARG_DBL, 0) \
+ X(end_finally,1, 0,0) \
+ X(eq, 1, 0,0) \
+ X(eq2, 1, 0,0) \
+ X(forin, 0, ARG_ADDR, 0) \
+ X(func, 1, ARG_UINT, 0) \
+ X(gt, 1, 0,0) \
+ X(gteq, 1, 0,0) \
+ X(ident, 1, ARG_BSTR, 0) \
+ X(identid, 1, ARG_BSTR, ARG_INT) \
+ X(in, 1, 0,0) \
+ X(instanceof, 1, 0,0) \
+ X(int, 1, ARG_INT, 0) \
+ X(jmp, 0, ARG_ADDR, 0) \
+ X(jmp_z, 0, ARG_ADDR, 0) \
+ X(lshift, 1, 0,0) \
+ X(lt, 1, 0,0) \
+ X(lteq, 1, 0,0) \
+ X(member, 1, ARG_BSTR, 0) \
+ X(memberid, 1, ARG_UINT, 0) \
+ X(minus, 1, 0,0) \
+ X(mod, 1, 0,0) \
+ X(mul, 1, 0,0) \
+ X(neg, 1, 0,0) \
+ X(neq, 1, 0,0) \
+ X(neq2, 1, 0,0) \
+ X(new, 1, ARG_UINT, 0) \
+ X(new_obj, 1, 0,0) \
+ X(null, 1, 0,0) \
+ X(obj_prop, 1, ARG_BSTR, 0) \
+ X(or, 1, 0,0) \
+ X(pop, 1, ARG_UINT, 0) \
+ X(pop_except, 1, 0,0) \
+ X(pop_scope, 1, 0,0) \
+ X(postinc, 1, ARG_INT, 0) \
+ X(preinc, 1, ARG_INT, 0) \
+ X(push_except,1, ARG_ADDR, ARG_BSTR) \
+ X(push_scope, 1, 0,0) \
+ X(regexp, 1, ARG_STR, ARG_UINT) \
+ X(rshift, 1, 0,0) \
+ X(rshift2, 1, 0,0) \
+ X(str, 1, ARG_STR, 0) \
+ X(this, 1, 0,0) \
+ X(throw, 0, 0,0) \
+ X(throw_ref, 0, ARG_UINT, 0) \
+ X(throw_type, 0, ARG_UINT, ARG_STR) \
+ X(tonum, 1, 0,0) \
+ X(typeof, 1, 0,0) \
+ X(typeofid, 1, 0,0) \
+ X(typeofident,1, 0,0) \
+ X(refval, 1, 0,0) \
+ X(ret, 0, 0,0) \
+ X(setret, 1, 0,0) \
+ X(sub, 1, 0,0) \
+ X(undefined, 1, 0,0) \
+ X(var_set, 1, ARG_BSTR, 0) \
+ X(void, 1, 0,0) \
+ X(xor, 1, 0,0)
- struct _parser_ctx_t *next;
-} parser_ctx_t;
+typedef enum {
+#define X(x,a,b,c) OP_##x,
+OP_LIST
+#undef X
+ OP_LAST
+} jsop_t;
+
+typedef union {
+ BSTR bstr;
+ LONG lng;
+ jsstr_t *str;
+ unsigned uint;
+} instr_arg_t;
+
+typedef enum {
+ ARG_NONE = 0,
+ ARG_ADDR,
+ ARG_BSTR,
+ ARG_DBL,
+ ARG_FUNC,
+ ARG_INT,
+ ARG_STR,
+ ARG_UINT
+} instr_arg_type_t;
+
+typedef struct {
+ jsop_t op;
+ union {
+ instr_arg_t arg[2];
+ double dbl;
+ } u;
+} instr_t;
+
+typedef struct _function_code_t {
+ BSTR name;
+ unsigned instr_off;
+
+ const WCHAR *source;
+ unsigned source_len;
+
+ unsigned func_cnt;
+ struct _function_code_t *funcs;
+
+ unsigned var_cnt;
+ BSTR *variables;
+
+ unsigned param_cnt;
+ BSTR *params;
+} function_code_t;
+
+typedef struct _bytecode_t {
+ LONG ref;
+
+ instr_t *instrs;
+ heap_pool_t heap;
+
+ function_code_t global_code;
-HRESULT script_parse(script_ctx_t*,const WCHAR*,const WCHAR*,parser_ctx_t**);
-void parser_release(parser_ctx_t*);
+ WCHAR *source;
-int parser_lex(void*,parser_ctx_t*);
+ BSTR *bstr_pool;
+ unsigned bstr_pool_size;
+ unsigned bstr_cnt;
-static inline void parser_addref(parser_ctx_t *ctx)
+ jsstr_t **str_pool;
+ unsigned str_pool_size;
+ unsigned str_cnt;
+
+ struct _bytecode_t *next;
+} bytecode_t;
+
+HRESULT compile_script(script_ctx_t*,const WCHAR*,const WCHAR*,const WCHAR*,BOOL,BOOL,bytecode_t**) DECLSPEC_HIDDEN;
+void release_bytecode(bytecode_t*) DECLSPEC_HIDDEN;
+
+static inline void bytecode_addref(bytecode_t *code)
{
- ctx->ref++;
+ code->ref++;
}
+HRESULT script_parse(script_ctx_t*,const WCHAR*,const WCHAR*,BOOL,parser_ctx_t**) DECLSPEC_HIDDEN;
+void parser_release(parser_ctx_t*) DECLSPEC_HIDDEN;
+
+int parser_lex(void*,parser_ctx_t*) DECLSPEC_HIDDEN;
+
static inline void *parser_alloc(parser_ctx_t *ctx, DWORD size)
{
- return jsheap_alloc(&ctx->heap, size);
+ return heap_pool_alloc(&ctx->heap, size);
}
static inline void *parser_alloc_tmp(parser_ctx_t *ctx, DWORD size)
{
- return jsheap_alloc(&ctx->script->tmp_heap, size);
+ return heap_pool_alloc(&ctx->script->tmp_heap, size);
}
typedef struct _scope_chain_t {
LONG ref;
- DispatchEx *obj;
+ jsdisp_t *jsobj;
+ IDispatch *obj;
struct _scope_chain_t *next;
} scope_chain_t;
-HRESULT scope_push(scope_chain_t*,DispatchEx*,scope_chain_t**);
-void scope_release(scope_chain_t*);
+HRESULT scope_push(scope_chain_t*,jsdisp_t*,IDispatch*,scope_chain_t**) DECLSPEC_HIDDEN;
+void scope_release(scope_chain_t*) DECLSPEC_HIDDEN;
static inline void scope_addref(scope_chain_t *scope)
{
scope->ref++;
}
+typedef struct _except_frame_t except_frame_t;
+
struct _exec_ctx_t {
LONG ref;
parser_ctx_t *parser;
+ bytecode_t *code;
+ script_ctx_t *script;
scope_chain_t *scope_chain;
- DispatchEx *var_disp;
+ jsdisp_t *var_disp;
IDispatch *this_obj;
+ function_code_t *func_code;
+ BOOL is_global;
+
+ jsval_t *stack;
+ unsigned stack_size;
+ unsigned top;
+ except_frame_t *except_frame;
+ jsval_t ret;
+
+ unsigned ip;
};
static inline void exec_addref(exec_ctx_t *ctx)
ctx->ref++;
}
-typedef enum {
- EXECT_PROGRAM,
- EXECT_FUNCTION,
- EXECT_EVAL
-} exec_type_t;
-
-void exec_release(exec_ctx_t*);
-HRESULT create_exec_ctx(script_ctx_t*,IDispatch*,DispatchEx*,scope_chain_t*,exec_ctx_t**);
-HRESULT exec_source(exec_ctx_t*,parser_ctx_t*,source_elements_t*,exec_type_t,jsexcept_t*,VARIANT*);
-
-typedef struct _statement_t statement_t;
-typedef struct _expression_t expression_t;
-typedef struct _parameter_t parameter_t;
-
-HRESULT create_source_function(parser_ctx_t*,parameter_t*,source_elements_t*,scope_chain_t*,
- const WCHAR*,DWORD,DispatchEx**);
+void exec_release(exec_ctx_t*) DECLSPEC_HIDDEN;
+HRESULT create_exec_ctx(script_ctx_t*,IDispatch*,jsdisp_t*,scope_chain_t*,BOOL,exec_ctx_t**) DECLSPEC_HIDDEN;
+HRESULT exec_source(exec_ctx_t*,bytecode_t*,function_code_t*,BOOL,jsval_t*) DECLSPEC_HIDDEN;
+HRESULT create_source_function(script_ctx_t*,bytecode_t*,function_code_t*,scope_chain_t*,jsdisp_t**) DECLSPEC_HIDDEN;
typedef enum {
- LT_INT,
LT_DOUBLE,
LT_STRING,
LT_BOOL,
typedef struct {
literal_type_t type;
union {
- LONG lval;
double dval;
const WCHAR *wstr;
- VARIANT_BOOL bval;
- IDispatch *disp;
+ BOOL bval;
struct {
const WCHAR *str;
DWORD str_len;
} u;
} literal_t;
-literal_t *parse_regexp(parser_ctx_t*);
+literal_t *parse_regexp(parser_ctx_t*) DECLSPEC_HIDDEN;
+literal_t *new_boolean_literal(parser_ctx_t*,BOOL) DECLSPEC_HIDDEN;
typedef struct _variable_declaration_t {
const WCHAR *identifier;
expression_t *expr;
struct _variable_declaration_t *next;
+ struct _variable_declaration_t *global_next; /* for compiler */
} variable_declaration_t;
-typedef struct {
- enum{
- RT_NORMAL,
- RT_RETURN,
- RT_BREAK,
- RT_CONTINUE
- } type;
- jsexcept_t ei;
-} return_type_t;
-
-typedef HRESULT (*statement_eval_t)(exec_ctx_t*,statement_t*,return_type_t*,VARIANT*);
+typedef enum {
+ STAT_BLOCK,
+ STAT_BREAK,
+ STAT_CONTINUE,
+ STAT_EMPTY,
+ STAT_EXPR,
+ STAT_FOR,
+ STAT_FORIN,
+ STAT_IF,
+ STAT_LABEL,
+ STAT_RETURN,
+ STAT_SWITCH,
+ STAT_THROW,
+ STAT_TRY,
+ STAT_VAR,
+ STAT_WHILE,
+ STAT_WITH
+} statement_type_t;
struct _statement_t {
- statement_eval_t eval;
+ statement_type_t type;
statement_t *next;
};
statement_t *finally_statement;
} try_statement_t;
-HRESULT block_statement_eval(exec_ctx_t*,statement_t*,return_type_t*,VARIANT*);
-HRESULT var_statement_eval(exec_ctx_t*,statement_t*,return_type_t*,VARIANT*);
-HRESULT empty_statement_eval(exec_ctx_t*,statement_t*,return_type_t*,VARIANT*);
-HRESULT expression_statement_eval(exec_ctx_t*,statement_t*,return_type_t*,VARIANT*);
-HRESULT if_statement_eval(exec_ctx_t*,statement_t*,return_type_t*,VARIANT*);
-HRESULT while_statement_eval(exec_ctx_t*,statement_t*,return_type_t*,VARIANT*);
-HRESULT for_statement_eval(exec_ctx_t*,statement_t*,return_type_t*,VARIANT*);
-HRESULT forin_statement_eval(exec_ctx_t*,statement_t*,return_type_t*,VARIANT*);
-HRESULT continue_statement_eval(exec_ctx_t*,statement_t*,return_type_t*,VARIANT*);
-HRESULT break_statement_eval(exec_ctx_t*,statement_t*,return_type_t*,VARIANT*);
-HRESULT return_statement_eval(exec_ctx_t*,statement_t*,return_type_t*,VARIANT*);
-HRESULT with_statement_eval(exec_ctx_t*,statement_t*,return_type_t*,VARIANT*);
-HRESULT labelled_statement_eval(exec_ctx_t*,statement_t*,return_type_t*,VARIANT*);
-HRESULT switch_statement_eval(exec_ctx_t*,statement_t*,return_type_t*,VARIANT*);
-HRESULT throw_statement_eval(exec_ctx_t*,statement_t*,return_type_t*,VARIANT*);
-HRESULT try_statement_eval(exec_ctx_t*,statement_t*,return_type_t*,VARIANT*);
-
typedef struct {
enum {
- EXPRVAL_VARIANT,
+ EXPRVAL_JSVAL,
EXPRVAL_IDREF,
- EXPRVAL_NAMEREF,
EXPRVAL_INVALID
} type;
union {
- VARIANT var;
+ jsval_t val;
struct {
IDispatch *disp;
DISPID id;
} idref;
- struct {
- IDispatch *disp;
- BSTR name;
- } nameref;
- BSTR identifier;
} u;
} exprval_t;
-typedef HRESULT (*expression_eval_t)(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
+typedef enum {
+ EXPR_COMMA,
+ EXPR_OR,
+ EXPR_AND,
+ EXPR_BOR,
+ EXPR_BXOR,
+ EXPR_BAND,
+ EXPR_INSTANCEOF,
+ EXPR_IN,
+ EXPR_ADD,
+ EXPR_SUB,
+ EXPR_MUL,
+ EXPR_DIV,
+ EXPR_MOD,
+ EXPR_DELETE,
+ EXPR_VOID,
+ EXPR_TYPEOF,
+ EXPR_MINUS,
+ EXPR_PLUS,
+ EXPR_POSTINC,
+ EXPR_POSTDEC,
+ EXPR_PREINC,
+ EXPR_PREDEC,
+ EXPR_EQ,
+ EXPR_EQEQ,
+ EXPR_NOTEQ,
+ EXPR_NOTEQEQ,
+ EXPR_LESS,
+ EXPR_LESSEQ,
+ EXPR_GREATER,
+ EXPR_GREATEREQ,
+ EXPR_BITNEG,
+ EXPR_LOGNEG,
+ EXPR_LSHIFT,
+ EXPR_RSHIFT,
+ EXPR_RRSHIFT,
+ EXPR_ASSIGN,
+ EXPR_ASSIGNLSHIFT,
+ EXPR_ASSIGNRSHIFT,
+ EXPR_ASSIGNRRSHIFT,
+ EXPR_ASSIGNADD,
+ EXPR_ASSIGNSUB,
+ EXPR_ASSIGNMUL,
+ EXPR_ASSIGNDIV,
+ EXPR_ASSIGNMOD,
+ EXPR_ASSIGNAND,
+ EXPR_ASSIGNOR,
+ EXPR_ASSIGNXOR,
+ EXPR_COND,
+ EXPR_ARRAY,
+ EXPR_MEMBER,
+ EXPR_NEW,
+ EXPR_CALL,
+ EXPR_THIS,
+ EXPR_FUNC,
+ EXPR_IDENT,
+ EXPR_ARRAYLIT,
+ EXPR_PROPVAL,
+ EXPR_LITERAL
+} expression_type_t;
struct _expression_t {
- expression_eval_t eval;
+ expression_type_t type;
};
-struct _parameter_t {
+typedef struct _parameter_t {
const WCHAR *identifier;
-
struct _parameter_t *next;
-};
+} parameter_t;
struct _source_elements_t {
statement_t *statement;
statement_t *statement_tail;
- function_declaration_t *functions;
- var_list_t *variables;
};
-struct _function_expression_t {
+typedef struct _function_expression_t {
expression_t expr;
const WCHAR *identifier;
parameter_t *parameter_list;
source_elements_t *source_elements;
const WCHAR *src_str;
DWORD src_len;
-};
+
+ struct _function_expression_t *next; /* for compiler */
+} function_expression_t;
typedef struct {
expression_t expr;
expression_t *false_expression;
} conditional_expression_t;
-typedef struct {
- expression_t expr;
- expression_t *member_expr;
- expression_t *expression;
-} array_expression_t;
-
typedef struct {
expression_t expr;
expression_t *expression;
expression_t expr;
prop_val_t *property_list;
} property_value_expression_t;
-
-typedef enum {
- EXPR_COMMA,
- EXPR_OR,
- EXPR_AND,
- EXPR_BOR,
- EXPR_BXOR,
- EXPR_BAND,
- EXPR_INSTANCEOF,
- EXPR_IN,
- EXPR_ADD,
- EXPR_SUB,
- EXPR_MUL,
- EXPR_DIV,
- EXPR_MOD,
- EXPR_DELETE,
- EXPR_VOID,
- EXPR_TYPEOF,
- EXPR_MINUS,
- EXPR_PLUS,
- EXPR_POSTINC,
- EXPR_POSTDEC,
- EXPR_PREINC,
- EXPR_PREDEC,
- EXPR_EQ,
- EXPR_EQEQ,
- EXPR_NOTEQ,
- EXPR_NOTEQEQ,
- EXPR_LESS,
- EXPR_LESSEQ,
- EXPR_GREATER,
- EXPR_GREATEREQ,
- EXPR_BITNEG,
- EXPR_LOGNEG,
- EXPR_LSHIFT,
- EXPR_RSHIFT,
- EXPR_RRSHIFT,
- EXPR_ASSIGN,
- EXPR_ASSIGNLSHIFT,
- EXPR_ASSIGNRSHIFT,
- EXPR_ASSIGNRRSHIFT,
- EXPR_ASSIGNADD,
- EXPR_ASSIGNSUB,
- EXPR_ASSIGNMUL,
- EXPR_ASSIGNDIV,
- EXPR_ASSIGNMOD,
- EXPR_ASSIGNAND,
- EXPR_ASSIGNOR,
- EXPR_ASSIGNXOR
-} expression_type_t;
-
-HRESULT function_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
-HRESULT conditional_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
-HRESULT array_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
-HRESULT member_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
-HRESULT new_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
-HRESULT call_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
-HRESULT this_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
-HRESULT identifier_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
-HRESULT literal_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
-HRESULT array_literal_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
-HRESULT property_value_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
-
-HRESULT comma_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
-HRESULT logical_or_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
-HRESULT logical_and_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
-HRESULT binary_or_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
-HRESULT binary_xor_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
-HRESULT binary_and_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
-HRESULT instanceof_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
-HRESULT in_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
-HRESULT add_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
-HRESULT sub_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
-HRESULT mul_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
-HRESULT div_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
-HRESULT mod_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
-HRESULT delete_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
-HRESULT void_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
-HRESULT typeof_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
-HRESULT minus_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
-HRESULT plus_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
-HRESULT post_increment_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
-HRESULT post_decrement_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
-HRESULT pre_increment_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
-HRESULT pre_decrement_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
-HRESULT equal_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
-HRESULT equal2_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
-HRESULT not_equal_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
-HRESULT not_equal2_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
-HRESULT less_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
-HRESULT lesseq_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
-HRESULT greater_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
-HRESULT greatereq_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
-HRESULT binary_negation_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
-HRESULT logical_negation_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
-HRESULT left_shift_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
-HRESULT right_shift_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
-HRESULT right2_shift_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
-HRESULT assign_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
-HRESULT assign_lshift_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
-HRESULT assign_rshift_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
-HRESULT assign_rrshift_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
-HRESULT assign_add_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
-HRESULT assign_sub_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
-HRESULT assign_mul_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
-HRESULT assign_div_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
-HRESULT assign_mod_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
-HRESULT assign_and_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
-HRESULT assign_or_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
-HRESULT assign_xor_expression_eval(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*);
WINE_DEFAULT_DEBUG_CHANNEL(jscript);
-typedef struct {
- DispatchEx dispex;
-
- VARIANT number;
- VARIANT description;
- VARIANT message;
-} ErrorInstance;
-
static const WCHAR descriptionW[] = {'d','e','s','c','r','i','p','t','i','o','n',0};
static const WCHAR messageW[] = {'m','e','s','s','a','g','e',0};
static const WCHAR nameW[] = {'n','a','m','e',0};
static const WCHAR numberW[] = {'n','u','m','b','e','r',0};
static const WCHAR toStringW[] = {'t','o','S','t','r','i','n','g',0};
-static inline ErrorInstance *error_from_vdisp(vdisp_t *vdisp)
-{
- return (ErrorInstance*)vdisp->u.jsdisp;
-}
-
-static inline ErrorInstance *error_this(vdisp_t *jsthis)
-{
- return is_vclass(jsthis, JSCLASS_ERROR) ? error_from_vdisp(jsthis) : NULL;
-}
-
-static HRESULT Error_number(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
- DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
-{
- ErrorInstance *This = error_from_vdisp(jsthis);
-
- TRACE("\n");
-
- switch(flags) {
- case DISPATCH_PROPERTYGET:
- return VariantCopy(retv, &This->number);
- case DISPATCH_PROPERTYPUT:
- return VariantCopy(&This->number, get_arg(dp, 0));
- default:
- FIXME("unimplemented flags %x\n", flags);
- return E_NOTIMPL;
- }
-}
-
-static HRESULT Error_description(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
- DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
-{
- ErrorInstance *This = error_from_vdisp(jsthis);
-
- TRACE("\n");
-
- switch(flags) {
- case DISPATCH_PROPERTYGET:
- return VariantCopy(retv, &This->description);
- case DISPATCH_PROPERTYPUT:
- return VariantCopy(&This->description, get_arg(dp, 0));
- default:
- FIXME("unimplemented flags %x\n", flags);
- return E_NOTIMPL;
- }
-}
-
-/* ECMA-262 3rd Edition 15.11.4.3 */
-static HRESULT Error_message(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
- DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
-{
- ErrorInstance *This = error_from_vdisp(jsthis);
-
- TRACE("\n");
-
- switch(flags) {
- case DISPATCH_PROPERTYGET:
- return VariantCopy(retv, &This->message);
- case DISPATCH_PROPERTYPUT:
- return VariantCopy(&This->message, get_arg(dp, 0));
- default:
- FIXME("unimplemented flags %x\n", flags);
- return E_NOTIMPL;
- }
-}
-
/* ECMA-262 3rd Edition 15.11.4.4 */
-static HRESULT Error_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
- DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT Error_toString(script_ctx_t *ctx, vdisp_t *vthis, WORD flags,
+ unsigned argc, jsval_t *argv, jsval_t *r)
{
- ErrorInstance *error;
- BSTR name, msg = NULL, ret = NULL;
- VARIANT v;
+ jsdisp_t *jsthis;
+ jsstr_t *name = NULL, *msg = NULL, *ret = NULL;
+ jsval_t v;
HRESULT hres;
- static const WCHAR str[] = {'[','o','b','j','e','c','t',' ','E','r','r','o','r',']',0};
+ static const WCHAR object_errorW[] = {'[','o','b','j','e','c','t',' ','E','r','r','o','r',']',0};
TRACE("\n");
- error = error_this(jsthis);
- if(ctx->version < 2 || !error) {
- if(retv) {
- V_VT(retv) = VT_BSTR;
- V_BSTR(retv) = SysAllocString(str);
- if(!V_BSTR(retv))
+ jsthis = get_jsdisp(vthis);
+ if(!jsthis || ctx->version < 2) {
+ if(r) {
+ jsstr_t *str;
+
+ str = jsstr_alloc(object_errorW);
+ if(!str)
return E_OUTOFMEMORY;
+ *r = jsval_string(str);
}
return S_OK;
}
- hres = jsdisp_propget_name(&error->dispex, nameW, &v, ei, caller);
+ hres = jsdisp_propget_name(jsthis, nameW, &v);
if(FAILED(hres))
return hres;
- hres = to_string(ctx, &v, ei, &name);
- VariantClear(&v);
- if(FAILED(hres))
- return hres;
+ if(!is_undefined(v)) {
+ hres = to_string(ctx, v, &name);
+ jsval_release(v);
+ if(FAILED(hres))
+ return hres;
+ }
- if(V_VT(&error->message) != VT_EMPTY) {
- hres = to_string(ctx, &error->message, ei, &msg);
- if(SUCCEEDED(hres) && !*msg) {
- SysFreeString(msg);
- msg = NULL;
+ hres = jsdisp_propget_name(jsthis, messageW, &v);
+ if(SUCCEEDED(hres)) {
+ if(!is_undefined(v)) {
+ hres = to_string(ctx, v, &msg);
+ jsval_release(v);
}
}
if(SUCCEEDED(hres)) {
- if(msg) {
- DWORD name_len, msg_len;
-
- name_len = SysStringLen(name);
- msg_len = SysStringLen(msg);
+ unsigned name_len = name ? jsstr_length(name) : 0;
+ unsigned msg_len = msg ? jsstr_length(msg) : 0;
- ret = SysAllocStringLen(NULL, name_len + msg_len + 2);
+ if(name_len && msg_len) {
+ ret = jsstr_alloc_buf(name_len + msg_len + 2);
if(ret) {
- memcpy(ret, name, name_len*sizeof(WCHAR));
- ret[name_len] = ':';
- ret[name_len+1] = ' ';
- memcpy(ret+name_len+2, msg, msg_len*sizeof(WCHAR));
+ jsstr_flush(name, ret->str);
+ ret->str[name_len] = ':';
+ ret->str[name_len+1] = ' ';
+ jsstr_flush(msg, ret->str+name_len+2);
}
- }else {
+ }else if(name_len) {
ret = name;
name = NULL;
+ }else if(msg_len) {
+ ret = msg;
+ msg = NULL;
+ }else {
+ ret = jsstr_alloc(object_errorW);
}
}
- SysFreeString(msg);
- SysFreeString(name);
+ if(msg)
+ jsstr_release(msg);
+ if(name)
+ jsstr_release(name);
if(FAILED(hres))
return hres;
if(!ret)
return E_OUTOFMEMORY;
- if(retv) {
- V_VT(retv) = VT_BSTR;
- V_BSTR(retv) = ret;
- }else {
- SysFreeString(ret);
- }
-
+ if(r)
+ *r = jsval_string(ret);
+ else
+ jsstr_release(ret);
return S_OK;
}
static HRESULT Error_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
- DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+ unsigned argc, jsval_t *argv, jsval_t *r)
{
TRACE("\n");
switch(flags) {
case INVOKE_FUNC:
- return throw_type_error(ctx, ei, IDS_NOT_FUNC, NULL);
+ return throw_type_error(ctx, JS_E_FUNCTION_EXPECTED, NULL);
default:
FIXME("unimplemented flags %x\n", flags);
return E_NOTIMPL;
return S_OK;
}
-static void Error_destructor(DispatchEx *dispex)
-{
- ErrorInstance *This = (ErrorInstance*)dispex;
-
- VariantClear(&This->number);
- VariantClear(&This->description);
- VariantClear(&This->message);
- heap_free(This);
-}
-
static const builtin_prop_t Error_props[] = {
- {descriptionW, Error_description, 0},
- {messageW, Error_message, 0},
- {numberW, Error_number, 0},
{toStringW, Error_toString, PROPF_METHOD}
};
{NULL, Error_value, 0},
sizeof(Error_props)/sizeof(*Error_props),
Error_props,
- Error_destructor,
+ NULL,
NULL
};
-static const builtin_prop_t ErrorInst_props[] = {
- {descriptionW, Error_description, 0},
- {messageW, Error_message, 0},
- {numberW, Error_number, 0},
-};
-
static const builtin_info_t ErrorInst_info = {
JSCLASS_ERROR,
{NULL, Error_value, 0},
- sizeof(ErrorInst_props)/sizeof(*ErrorInst_props),
- ErrorInst_props,
- Error_destructor,
+ 0,
+ NULL,
+ NULL,
NULL
};
-static HRESULT alloc_error(script_ctx_t *ctx, DispatchEx *prototype,
- DispatchEx *constr, ErrorInstance **ret)
+static HRESULT alloc_error(script_ctx_t *ctx, jsdisp_t *prototype,
+ jsdisp_t *constr, jsdisp_t **ret)
{
- ErrorInstance *err;
+ jsdisp_t *err;
HRESULT hres;
- err = heap_alloc_zero(sizeof(ErrorInstance));
+ err = heap_alloc_zero(sizeof(*err));
if(!err)
return E_OUTOFMEMORY;
if(prototype)
- hres = init_dispex(&err->dispex, ctx, &Error_info, prototype);
+ hres = init_dispex(err, ctx, &Error_info, prototype);
else
- hres = init_dispex_from_constr(&err->dispex, ctx, &ErrorInst_info,
+ hres = init_dispex_from_constr(err, ctx, &ErrorInst_info,
constr ? constr : ctx->error_constr);
if(FAILED(hres)) {
heap_free(err);
return S_OK;
}
-static HRESULT create_error(script_ctx_t *ctx, DispatchEx *constr,
- const UINT *number, const WCHAR *msg, DispatchEx **ret)
+static HRESULT create_error(script_ctx_t *ctx, jsdisp_t *constr,
+ UINT number, jsstr_t *msg, jsdisp_t **ret)
{
- ErrorInstance *err;
+ jsdisp_t *err;
HRESULT hres;
hres = alloc_error(ctx, NULL, constr, &err);
if(FAILED(hres))
return hres;
- if(number) {
- V_VT(&err->number) = VT_I4;
- V_I4(&err->number) = *number;
+ hres = jsdisp_propput_dontenum(err, numberW, jsval_number((INT)number));
+ if(FAILED(hres)) {
+ jsdisp_release(err);
+ return hres;
}
- V_VT(&err->message) = VT_BSTR;
- if(msg) V_BSTR(&err->message) = SysAllocString(msg);
- else V_BSTR(&err->message) = SysAllocStringLen(NULL, 0);
-
- VariantCopy(&err->description, &err->message);
-
- if(!V_BSTR(&err->message)) {
- heap_free(err);
- return E_OUTOFMEMORY;
+ hres = jsdisp_propput_name(err, messageW, jsval_string(msg));
+ if(SUCCEEDED(hres))
+ hres = jsdisp_propput_dontenum(err, descriptionW, jsval_string(msg));
+ if(FAILED(hres)) {
+ jsdisp_release(err);
+ return hres;
}
- *ret = &err->dispex;
+ *ret = err;
return S_OK;
}
-static HRESULT error_constr(script_ctx_t *ctx, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, DispatchEx *constr) {
- DispatchEx *err;
- VARIANT numv;
- UINT num;
- BSTR msg = NULL;
+static HRESULT error_constr(script_ctx_t *ctx, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r, jsdisp_t *constr) {
+ jsdisp_t *err;
+ UINT num = 0;
+ jsstr_t *msg = NULL;
HRESULT hres;
- V_VT(&numv) = VT_NULL;
-
- if(arg_cnt(dp)) {
- hres = to_number(ctx, get_arg(dp, 0), ei, &numv);
- if(FAILED(hres) || (V_VT(&numv)==VT_R8 && isnan(V_R8(&numv))))
- hres = to_string(ctx, get_arg(dp, 0), ei, &msg);
- else if(V_VT(&numv) == VT_I4)
- num = V_I4(&numv);
- else
- num = V_R8(&numv);
+ if(argc) {
+ double n;
+ hres = to_number(ctx, argv[0], &n);
+ if(FAILED(hres)) /* FIXME: really? */
+ n = NAN;
+ if(isnan(n))
+ hres = to_string(ctx, argv[0], &msg);
if(FAILED(hres))
return hres;
+ num = n;
}
- if(arg_cnt(dp)>1 && !msg) {
- hres = to_string(ctx, get_arg(dp, 1), ei, &msg);
- if(FAILED(hres))
- return hres;
+ if(!msg) {
+ if(argc > 1) {
+ hres = to_string(ctx, argv[1], &msg);
+ if(FAILED(hres))
+ return hres;
+ }else {
+ msg = jsstr_empty();
+ }
}
switch(flags) {
case INVOKE_FUNC:
case DISPATCH_CONSTRUCT:
- if(V_VT(&numv) == VT_NULL)
- hres = create_error(ctx, constr, NULL, msg, &err);
- else
- hres = create_error(ctx, constr, &num, msg, &err);
- SysFreeString(msg);
-
+ hres = create_error(ctx, constr, num, msg, &err);
+ jsstr_release(msg);
if(FAILED(hres))
return hres;
- if(retv) {
- V_VT(retv) = VT_DISPATCH;
- V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(err);
- }
+ if(r)
+ *r = jsval_obj(err);
else
jsdisp_release(err);
-
return S_OK;
default:
+ if(msg)
+ jsstr_release(msg);
FIXME("unimplemented flags %x\n", flags);
return E_NOTIMPL;
}
}
static HRESULT ErrorConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
- DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+ unsigned argc, jsval_t *argv, jsval_t *r)
{
TRACE("\n");
- return error_constr(ctx, flags, dp, retv, ei, ctx->error_constr);
+ return error_constr(ctx, flags, argc, argv, r, ctx->error_constr);
}
static HRESULT EvalErrorConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
- DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+ unsigned argc, jsval_t *argv, jsval_t *r)
{
TRACE("\n");
- return error_constr(ctx, flags, dp, retv, ei, ctx->eval_error_constr);
+ return error_constr(ctx, flags, argc, argv, r, ctx->eval_error_constr);
}
static HRESULT RangeErrorConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
- DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+ unsigned argc, jsval_t *argv, jsval_t *r)
{
TRACE("\n");
- return error_constr(ctx, flags, dp, retv, ei, ctx->range_error_constr);
+ return error_constr(ctx, flags, argc, argv, r, ctx->range_error_constr);
}
static HRESULT ReferenceErrorConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
- DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+ unsigned argc, jsval_t *argv, jsval_t *r)
{
TRACE("\n");
- return error_constr(ctx, flags, dp, retv, ei, ctx->reference_error_constr);
+ return error_constr(ctx, flags, argc, argv, r, ctx->reference_error_constr);
}
static HRESULT RegExpErrorConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
- DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+ unsigned argc, jsval_t *argv, jsval_t *r)
{
TRACE("\n");
- return error_constr(ctx, flags, dp, retv, ei, ctx->regexp_error_constr);
+ return error_constr(ctx, flags, argc, argv, r, ctx->regexp_error_constr);
}
static HRESULT SyntaxErrorConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
- DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+ unsigned argc, jsval_t *argv, jsval_t *r)
{
TRACE("\n");
- return error_constr(ctx, flags, dp, retv, ei, ctx->syntax_error_constr);
+ return error_constr(ctx, flags, argc, argv, r, ctx->syntax_error_constr);
}
static HRESULT TypeErrorConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
- DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+ unsigned argc, jsval_t *argv, jsval_t *r)
{
TRACE("\n");
- return error_constr(ctx, flags, dp, retv, ei, ctx->type_error_constr);
+ return error_constr(ctx, flags, argc, argv, r, ctx->type_error_constr);
}
static HRESULT URIErrorConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
- DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+ unsigned argc, jsval_t *argv, jsval_t *r)
{
TRACE("\n");
- return error_constr(ctx, flags, dp, retv, ei, ctx->uri_error_constr);
+ return error_constr(ctx, flags, argc, argv, r, ctx->uri_error_constr);
}
-HRESULT init_error_constr(script_ctx_t *ctx, DispatchEx *object_prototype)
+HRESULT init_error_constr(script_ctx_t *ctx, jsdisp_t *object_prototype)
{
static const WCHAR ErrorW[] = {'E','r','r','o','r',0};
static const WCHAR EvalErrorW[] = {'E','v','a','l','E','r','r','o','r',0};
static const WCHAR URIErrorW[] = {'U','R','I','E','r','r','o','r',0};
static const WCHAR *names[] = {ErrorW, EvalErrorW, RangeErrorW,
ReferenceErrorW, RegExpErrorW, SyntaxErrorW, TypeErrorW, URIErrorW};
- DispatchEx **constr_addr[] = {&ctx->error_constr, &ctx->eval_error_constr,
+ jsdisp_t **constr_addr[] = {&ctx->error_constr, &ctx->eval_error_constr,
&ctx->range_error_constr, &ctx->reference_error_constr, &ctx->regexp_error_constr,
&ctx->syntax_error_constr, &ctx->type_error_constr,
&ctx->uri_error_constr};
RangeErrorConstr_value, ReferenceErrorConstr_value, RegExpErrorConstr_value,
SyntaxErrorConstr_value, TypeErrorConstr_value, URIErrorConstr_value};
- ErrorInstance *err;
- INT i;
- VARIANT v;
+ jsdisp_t *err;
+ unsigned int i;
+ jsstr_t *str;
HRESULT hres;
for(i=0; i < sizeof(names)/sizeof(names[0]); i++) {
if(FAILED(hres))
return hres;
- V_VT(&v) = VT_BSTR;
- V_BSTR(&v) = SysAllocString(names[i]);
- if(!V_BSTR(&v)) {
- jsdisp_release(&err->dispex);
+ str = jsstr_alloc(names[i]);
+ if(!str) {
+ jsdisp_release(err);
return E_OUTOFMEMORY;
}
- hres = jsdisp_propput_name(&err->dispex, nameW, &v, NULL/*FIXME*/, NULL/*FIXME*/);
-
+ hres = jsdisp_propput_dontenum(err, nameW, jsval_string(str));
+ jsstr_release(str);
if(SUCCEEDED(hres))
- hres = create_builtin_function(ctx, constr_val[i], names[i], NULL,
- PROPF_CONSTR|1, &err->dispex, constr_addr[i]);
+ hres = create_builtin_constructor(ctx, constr_val[i], names[i], NULL,
+ PROPF_CONSTR|1, err, constr_addr[i]);
- jsdisp_release(&err->dispex);
- VariantClear(&v);
+ jsdisp_release(err);
if(FAILED(hres))
return hres;
}
return S_OK;
}
-static HRESULT throw_error(script_ctx_t *ctx, jsexcept_t *ei, UINT id, const WCHAR *str, DispatchEx *constr)
+static HRESULT throw_error(script_ctx_t *ctx, HRESULT error, const WCHAR *str, jsdisp_t *constr)
{
WCHAR buf[1024], *pos = NULL;
- DispatchEx *err;
+ jsdisp_t *err;
+ jsstr_t *msg;
HRESULT hres;
+ if(!is_jscript_error(error))
+ return error;
+
buf[0] = '\0';
- LoadStringW(jscript_hinstance, id&0xFFFF, buf, sizeof(buf)/sizeof(WCHAR));
+ LoadStringW(jscript_hinstance, HRESULT_CODE(error), buf, sizeof(buf)/sizeof(WCHAR));
if(str) pos = strchrW(buf, '|');
if(pos) {
WARN("%s\n", debugstr_w(buf));
- id |= JSCRIPT_ERROR;
- hres = create_error(ctx, constr, &id, buf, &err);
+ msg = jsstr_alloc(buf);
+ if(!msg)
+ return E_OUTOFMEMORY;
+
+ hres = create_error(ctx, constr, error, msg, &err);
+ jsstr_release(msg);
if(FAILED(hres))
return hres;
- if(!ei)
- return id;
-
- V_VT(&ei->var) = VT_DISPATCH;
- V_DISPATCH(&ei->var) = (IDispatch*)_IDispatchEx_(err);
-
- return id;
+ jsval_release(ctx->ei.val);
+ ctx->ei.val = jsval_obj(err);
+ return error;
}
-HRESULT throw_generic_error(script_ctx_t *ctx, jsexcept_t *ei, UINT id, const WCHAR *str)
+HRESULT throw_generic_error(script_ctx_t *ctx, HRESULT error, const WCHAR *str)
{
- return throw_error(ctx, ei, id, str, ctx->error_constr);
+ return throw_error(ctx, error, str, ctx->error_constr);
}
-HRESULT throw_range_error(script_ctx_t *ctx, jsexcept_t *ei, UINT id, const WCHAR *str)
+HRESULT throw_range_error(script_ctx_t *ctx, HRESULT error, const WCHAR *str)
{
- return throw_error(ctx, ei, id, str, ctx->range_error_constr);
+ return throw_error(ctx, error, str, ctx->range_error_constr);
}
-HRESULT throw_reference_error(script_ctx_t *ctx, jsexcept_t *ei, UINT id, const WCHAR *str)
+HRESULT throw_reference_error(script_ctx_t *ctx, HRESULT error, const WCHAR *str)
{
- return throw_error(ctx, ei, id, str, ctx->reference_error_constr);
+ return throw_error(ctx, error, str, ctx->reference_error_constr);
}
-HRESULT throw_regexp_error(script_ctx_t *ctx, jsexcept_t *ei, UINT id, const WCHAR *str)
+HRESULT throw_regexp_error(script_ctx_t *ctx, HRESULT error, const WCHAR *str)
{
- return throw_error(ctx, ei, id, str, ctx->regexp_error_constr);
+ return throw_error(ctx, error, str, ctx->regexp_error_constr);
}
-HRESULT throw_syntax_error(script_ctx_t *ctx, jsexcept_t *ei, UINT id, const WCHAR *str)
+HRESULT throw_syntax_error(script_ctx_t *ctx, HRESULT error, const WCHAR *str)
{
- return throw_error(ctx, ei, id, str, ctx->syntax_error_constr);
+ return throw_error(ctx, error, str, ctx->syntax_error_constr);
}
-HRESULT throw_type_error(script_ctx_t *ctx, jsexcept_t *ei, UINT id, const WCHAR *str)
+HRESULT throw_type_error(script_ctx_t *ctx, HRESULT error, const WCHAR *str)
{
- return throw_error(ctx, ei, id, str, ctx->type_error_constr);
+ return throw_error(ctx, error, str, ctx->type_error_constr);
}
-HRESULT throw_uri_error(script_ctx_t *ctx, jsexcept_t *ei, UINT id, const WCHAR *str)
+HRESULT throw_uri_error(script_ctx_t *ctx, HRESULT error, const WCHAR *str)
{
- return throw_error(ctx, ei, id, str, ctx->uri_error_constr);
+ return throw_error(ctx, error, str, ctx->uri_error_constr);
}
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
+#include <assert.h>
+
#include "jscript.h"
#include "engine.h"
WINE_DEFAULT_DEBUG_CHANNEL(jscript);
typedef struct {
- DispatchEx dispex;
+ jsdisp_t dispex;
builtin_invoke_t value_proc;
const WCHAR *name;
DWORD flags;
- source_elements_t *source;
- parameter_t *parameters;
scope_chain_t *scope_chain;
- parser_ctx_t *parser;
- const WCHAR *src_str;
- DWORD src_len;
+ bytecode_t *code;
+ function_code_t *func_code;
DWORD length;
+ jsdisp_t *arguments;
} FunctionInstance;
+typedef struct {
+ jsdisp_t jsdisp;
+ FunctionInstance *function;
+ jsdisp_t *var_obj;
+} ArgumentsInstance;
+
static inline FunctionInstance *function_from_vdisp(vdisp_t *vdisp)
{
return (FunctionInstance*)vdisp->u.jsdisp;
static const WCHAR toStringW[] = {'t','o','S','t','r','i','n','g',0};
static const WCHAR applyW[] = {'a','p','p','l','y',0};
static const WCHAR callW[] = {'c','a','l','l',0};
+static const WCHAR argumentsW[] = {'a','r','g','u','m','e','n','t','s',0};
-static IDispatch *get_this(DISPPARAMS *dp)
+static HRESULT init_parameters(jsdisp_t *var_disp, FunctionInstance *function, unsigned argc, jsval_t *argv)
{
- DWORD i;
-
- for(i=0; i < dp->cNamedArgs; i++) {
- if(dp->rgdispidNamedArgs[i] == DISPID_THIS) {
- if(V_VT(dp->rgvarg+i) == VT_DISPATCH)
- return V_DISPATCH(dp->rgvarg+i);
+ DWORD i=0;
+ HRESULT hres;
- WARN("This is not VT_DISPATCH\n");
- return NULL;
- }
+ for(i=0; i < function->func_code->param_cnt; i++) {
+ hres = jsdisp_propput_name(var_disp, function->func_code->params[i],
+ i < argc ? argv[i] : jsval_undefined());
+ if(FAILED(hres))
+ return hres;
}
- TRACE("no this passed\n");
- return NULL;
+ return S_OK;
}
-static HRESULT init_parameters(DispatchEx *var_disp, FunctionInstance *function, DISPPARAMS *dp,
- jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT Arguments_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- parameter_t *param;
- VARIANT var_empty;
- DWORD cargs, i=0;
- HRESULT hres;
+ FIXME("\n");
+ return E_NOTIMPL;
+}
- V_VT(&var_empty) = VT_EMPTY;
- cargs = arg_cnt(dp);
+static void Arguments_destructor(jsdisp_t *jsdisp)
+{
+ ArgumentsInstance *arguments = (ArgumentsInstance*)jsdisp;
- for(param = function->parameters; param; param = param->next) {
- hres = jsdisp_propput_name(var_disp, param->identifier,
- i < cargs ? get_arg(dp,i) : &var_empty, ei, caller);
- if(FAILED(hres))
- return hres;
+ jsdisp_release(&arguments->function->dispex);
+ jsdisp_release(arguments->var_obj);
+ heap_free(arguments);
+}
- i++;
- }
+static unsigned Arguments_idx_length(jsdisp_t *jsdisp)
+{
+ ArgumentsInstance *arguments = (ArgumentsInstance*)jsdisp;
+ return arguments->function->length;
+}
- return S_OK;
+static HRESULT Arguments_idx_get(jsdisp_t *jsdisp, unsigned idx, jsval_t *res)
+{
+ ArgumentsInstance *arguments = (ArgumentsInstance*)jsdisp;
+
+ TRACE("%p[%u]\n", arguments, idx);
+
+ /* FIXME: Accessing by name won't work for duplicated argument names */
+ return jsdisp_propget_name(arguments->var_obj, arguments->function->func_code->params[idx], res);
}
-static HRESULT Arguments_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT Arguments_idx_put(jsdisp_t *jsdisp, unsigned idx, jsval_t val)
{
- FIXME("\n");
- return E_NOTIMPL;
+ ArgumentsInstance *arguments = (ArgumentsInstance*)jsdisp;
+
+ TRACE("%p[%u] = %s\n", arguments, idx, debugstr_jsval(val));
+
+ /* FIXME: Accessing by name won't work for duplicated argument names */
+ return jsdisp_propput_name(arguments->var_obj, arguments->function->func_code->params[idx], val);
}
static const builtin_info_t Arguments_info = {
JSCLASS_ARGUMENTS,
{NULL, Arguments_value, 0},
0, NULL,
+ Arguments_destructor,
NULL,
- NULL
+ Arguments_idx_length,
+ Arguments_idx_get,
+ Arguments_idx_put
};
-static HRESULT create_arguments(script_ctx_t *ctx, IDispatch *calee, DISPPARAMS *dp,
- jsexcept_t *ei, IServiceProvider *caller, DispatchEx **ret)
+static HRESULT create_arguments(script_ctx_t *ctx, FunctionInstance *calee, jsdisp_t *var_obj,
+ unsigned argc, jsval_t *argv, jsdisp_t **ret)
{
- DispatchEx *args;
- VARIANT var;
- DWORD i;
+ ArgumentsInstance *args;
+ unsigned i;
HRESULT hres;
static const WCHAR caleeW[] = {'c','a','l','l','e','e',0};
- args = heap_alloc_zero(sizeof(DispatchEx));
+ args = heap_alloc_zero(sizeof(*args));
if(!args)
return E_OUTOFMEMORY;
- hres = init_dispex_from_constr(args, ctx, &Arguments_info, ctx->object_constr);
+ hres = init_dispex_from_constr(&args->jsdisp, ctx, &Arguments_info, ctx->object_constr);
if(FAILED(hres)) {
heap_free(args);
return hres;
}
- for(i=0; i < arg_cnt(dp); i++) {
- hres = jsdisp_propput_idx(args, i, get_arg(dp,i), ei, caller);
+ jsdisp_addref(&calee->dispex);
+ args->function = calee;
+ args->var_obj = jsdisp_addref(var_obj);
+
+ /* Store unnamed arguments directly in arguments object */
+ for(i = calee->length; i < argc; i++) {
+ WCHAR buf[12];
+
+ static const WCHAR formatW[] = {'%','d',0};
+
+ sprintfW(buf, formatW, i);
+ hres = jsdisp_propput_dontenum(&args->jsdisp, buf, argv[i]);
if(FAILED(hres))
break;
}
if(SUCCEEDED(hres)) {
- V_VT(&var) = VT_I4;
- V_I4(&var) = arg_cnt(dp);
- hres = jsdisp_propput_name(args, lengthW, &var, ei, caller);
-
- if(SUCCEEDED(hres)) {
- V_VT(&var) = VT_DISPATCH;
- V_DISPATCH(&var) = calee;
- hres = jsdisp_propput_name(args, caleeW, &var, ei, caller);
- }
+ hres = jsdisp_propput_dontenum(&args->jsdisp, lengthW, jsval_number(argc));
+ if(SUCCEEDED(hres))
+ hres = jsdisp_propput_dontenum(&args->jsdisp, caleeW, jsval_disp(to_disp(&calee->dispex)));
}
-
if(FAILED(hres)) {
- jsdisp_release(args);
+ jsdisp_release(&args->jsdisp);
return hres;
}
- *ret = args;
+ *ret = &args->jsdisp;
return S_OK;
}
-static HRESULT create_var_disp(script_ctx_t *ctx, FunctionInstance *function, DISPPARAMS *dp, jsexcept_t *ei,
- IServiceProvider *caller, DispatchEx **ret)
+static HRESULT create_var_disp(script_ctx_t *ctx, FunctionInstance *function, unsigned argc, jsval_t *argv, jsdisp_t **ret)
{
- DispatchEx *var_disp, *arg_disp;
+ jsdisp_t *var_disp;
HRESULT hres;
- static const WCHAR argumentsW[] = {'a','r','g','u','m','e','n','t','s',0};
-
hres = create_dispex(ctx, NULL, NULL, &var_disp);
if(FAILED(hres))
return hres;
- hres = create_arguments(ctx, (IDispatch*)_IDispatchEx_(&function->dispex),
- dp, ei, caller, &arg_disp);
- if(SUCCEEDED(hres)) {
- VARIANT var;
-
- V_VT(&var) = VT_DISPATCH;
- V_DISPATCH(&var) = (IDispatch*)_IDispatchEx_(arg_disp);
- hres = jsdisp_propput_name(var_disp, argumentsW, &var, ei, caller);
- jsdisp_release(arg_disp);
- }
-
- if(SUCCEEDED(hres))
- hres = init_parameters(var_disp, function, dp, ei, caller);
+ hres = init_parameters(var_disp, function, argc, argv);
if(FAILED(hres)) {
jsdisp_release(var_disp);
return hres;
return S_OK;
}
-static HRESULT invoke_source(script_ctx_t *ctx, FunctionInstance *function, IDispatch *this_obj, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT invoke_source(script_ctx_t *ctx, FunctionInstance *function, IDispatch *this_obj, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- DispatchEx *var_disp;
+ jsdisp_t *var_disp, *arg_disp;
exec_ctx_t *exec_ctx;
scope_chain_t *scope;
HRESULT hres;
- if(!function->source) {
+ if(!function->func_code) {
FIXME("no source\n");
return E_FAIL;
}
- hres = create_var_disp(ctx, function, dp, ei, caller, &var_disp);
+ hres = create_var_disp(ctx, function, argc, argv, &var_disp);
if(FAILED(hres))
return hres;
- hres = scope_push(function->scope_chain, var_disp, &scope);
+ hres = create_arguments(ctx, function, var_disp, argc, argv, &arg_disp);
+ if(FAILED(hres)) {
+ jsdisp_release(var_disp);
+ return hres;
+ }
+
+ hres = jsdisp_propput(var_disp, argumentsW, PROPF_DONTDELETE, jsval_obj(arg_disp));
+ if(FAILED(hres)) {
+ jsdisp_release(arg_disp);
+ jsdisp_release(var_disp);
+ return hres;
+ }
+
+ hres = scope_push(function->scope_chain, var_disp, to_disp(var_disp), &scope);
if(SUCCEEDED(hres)) {
- hres = create_exec_ctx(ctx, this_obj, var_disp, scope, &exec_ctx);
+ hres = create_exec_ctx(ctx, this_obj, var_disp, scope, FALSE, &exec_ctx);
scope_release(scope);
+
+ if(SUCCEEDED(hres)) {
+ jsdisp_t *prev_args;
+
+ prev_args = function->arguments;
+ function->arguments = arg_disp;
+ hres = exec_source(exec_ctx, function->code, function->func_code, FALSE, r);
+ function->arguments = prev_args;
+
+ exec_release(exec_ctx);
+ }
}
- jsdisp_release(var_disp);
- if(FAILED(hres))
- return hres;
- hres = exec_source(exec_ctx, function->parser, function->source, EXECT_FUNCTION, ei, retv);
- exec_release(exec_ctx);
+ /* Reset arguments value to cut the reference cycle. Note that since all activation contexts have
+ * their own arguments property, it's impossible to use prototype's one during name lookup */
+ jsdisp_propput_name(var_disp, argumentsW, jsval_undefined());
+ jsdisp_release(arg_disp);
+ jsdisp_release(var_disp);
return hres;
}
-static HRESULT invoke_constructor(script_ctx_t *ctx, FunctionInstance *function, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT invoke_constructor(script_ctx_t *ctx, FunctionInstance *function, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- DispatchEx *this_obj;
- VARIANT var;
+ jsdisp_t *this_obj;
+ jsval_t var;
HRESULT hres;
hres = create_object(ctx, &function->dispex, &this_obj);
if(FAILED(hres))
return hres;
- hres = invoke_source(ctx, function, (IDispatch*)_IDispatchEx_(this_obj), dp, &var, ei, caller);
+ hres = invoke_source(ctx, function, to_disp(this_obj), argc, argv, &var);
if(FAILED(hres)) {
jsdisp_release(this_obj);
return hres;
}
- V_VT(retv) = VT_DISPATCH;
- if(V_VT(&var) == VT_DISPATCH) {
+ if(is_object_instance(var)) {
jsdisp_release(this_obj);
- V_DISPATCH(retv) = V_DISPATCH(&var);
+ *r = var;
}else {
- VariantClear(&var);
- V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(this_obj);
+ jsval_release(var);
+ *r = jsval_obj(this_obj);
}
return S_OK;
}
-static HRESULT invoke_value_proc(script_ctx_t *ctx, FunctionInstance *function, IDispatch *this_disp, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT invoke_value_proc(script_ctx_t *ctx, FunctionInstance *function, IDispatch *this_disp, WORD flags,
+ unsigned argc, jsval_t *argv, jsval_t *r)
{
vdisp_t vthis;
HRESULT hres;
else
set_jsdisp(&vthis, ctx->global);
- hres = function->value_proc(ctx, &vthis, flags, dp, retv, ei, caller);
+ hres = function->value_proc(ctx, &vthis, flags, argc, argv, r);
vdisp_release(&vthis);
return hres;
}
-static HRESULT call_function(script_ctx_t *ctx, FunctionInstance *function, IDispatch *this_obj, DISPPARAMS *args,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT call_function(script_ctx_t *ctx, FunctionInstance *function, IDispatch *this_obj,
+ unsigned argc, jsval_t *argv, jsval_t *r)
{
if(function->value_proc)
- return invoke_value_proc(ctx, function, this_obj, DISPATCH_METHOD, args, retv, ei, caller);
+ return invoke_value_proc(ctx, function, this_obj, DISPATCH_METHOD, argc, argv, r);
- return invoke_source(ctx, function, this_obj, args, retv, ei, caller);
+ return invoke_source(ctx, function, this_obj, argc, argv, r);
}
-static HRESULT function_to_string(FunctionInstance *function, BSTR *ret)
+static HRESULT function_to_string(FunctionInstance *function, jsstr_t **ret)
{
- BSTR str;
+ jsstr_t *str;
static const WCHAR native_prefixW[] = {'\n','f','u','n','c','t','i','o','n',' '};
static const WCHAR native_suffixW[] =
DWORD name_len;
name_len = strlenW(function->name);
- str = SysAllocStringLen(NULL, sizeof(native_prefixW) + name_len*sizeof(WCHAR) + sizeof(native_suffixW));
+ str = jsstr_alloc_buf((sizeof(native_prefixW)+sizeof(native_suffixW))/sizeof(WCHAR) + name_len);
if(!str)
return E_OUTOFMEMORY;
- memcpy(str, native_prefixW, sizeof(native_prefixW));
- memcpy(str + sizeof(native_prefixW)/sizeof(WCHAR), function->name, name_len*sizeof(WCHAR));
- memcpy(str + sizeof(native_prefixW)/sizeof(WCHAR) + name_len, native_suffixW, sizeof(native_suffixW));
+ memcpy(str->str, native_prefixW, sizeof(native_prefixW));
+ memcpy(str->str + sizeof(native_prefixW)/sizeof(WCHAR), function->name, name_len*sizeof(WCHAR));
+ memcpy(str->str + sizeof(native_prefixW)/sizeof(WCHAR) + name_len, native_suffixW, sizeof(native_suffixW));
}else {
- str = SysAllocStringLen(function->src_str, function->src_len);
+ str = jsstr_alloc_len(function->func_code->source, function->func_code->source_len);
if(!str)
return E_OUTOFMEMORY;
}
return S_OK;
}
-static HRESULT Function_length(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+HRESULT Function_invoke(jsdisp_t *func_this, IDispatch *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r)
+{
+ FunctionInstance *function;
+
+ TRACE("func %p this %p\n", func_this, jsthis);
+
+ assert(is_class(func_this, JSCLASS_FUNCTION));
+ function = (FunctionInstance*)func_this;
+
+ if(function->value_proc)
+ return invoke_value_proc(function->dispex.ctx, function, jsthis, flags, argc, argv, r);
+
+ if(flags == DISPATCH_CONSTRUCT)
+ return invoke_constructor(function->dispex.ctx, function, argc, argv, r);
+
+ assert(flags == DISPATCH_METHOD);
+ return invoke_source(function->dispex.ctx, function, jsthis, argc, argv, r);
+}
+
+static HRESULT Function_length(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
FunctionInstance *This = function_from_vdisp(jsthis);
switch(flags) {
case DISPATCH_PROPERTYGET:
- V_VT(retv) = VT_I4;
- V_I4(retv) = This->length;
+ *r = jsval_number(This->length);
break;
default:
FIXME("unimplemented flags %x\n", flags);
return S_OK;
}
-static HRESULT Function_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT Function_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
FunctionInstance *function;
- BSTR str;
+ jsstr_t *str;
HRESULT hres;
TRACE("\n");
if(!(function = function_this(jsthis)))
- return throw_type_error(ctx, ei, IDS_NOT_FUNC, NULL);
+ return throw_type_error(ctx, JS_E_FUNCTION_EXPECTED, NULL);
hres = function_to_string(function, &str);
if(FAILED(hres))
return hres;
- if(retv) {
- V_VT(retv) = VT_BSTR;
- V_BSTR(retv) = str;
- }else {
- SysFreeString(str);
- }
+ if(r)
+ *r = jsval_string(str);
+ else
+ jsstr_release(str);
return S_OK;
}
-static HRESULT array_to_args(script_ctx_t *ctx, DispatchEx *arg_array, jsexcept_t *ei, IServiceProvider *caller,
- DISPPARAMS *args)
+static HRESULT array_to_args(script_ctx_t *ctx, jsdisp_t *arg_array, unsigned *argc, jsval_t **ret)
{
- VARIANT var, *argv;
+ jsval_t *argv, val;
DWORD length, i;
HRESULT hres;
- hres = jsdisp_propget_name(arg_array, lengthW, &var, ei, NULL/*FIXME*/);
+ hres = jsdisp_propget_name(arg_array, lengthW, &val);
if(FAILED(hres))
return hres;
- hres = to_uint32(ctx, &var, ei, &length);
- VariantClear(&var);
+ hres = to_uint32(ctx, val, &length);
+ jsval_release(val);
if(FAILED(hres))
return hres;
- argv = heap_alloc(length * sizeof(VARIANT));
+ argv = heap_alloc(length * sizeof(*argv));
if(!argv)
return E_OUTOFMEMORY;
for(i=0; i<length; i++) {
- hres = jsdisp_get_idx(arg_array, i, argv+i, ei, caller);
- if(hres == DISP_E_UNKNOWNNAME)
- V_VT(argv+i) = VT_EMPTY;
- else if(FAILED(hres)) {
+ hres = jsdisp_get_idx(arg_array, i, argv+i);
+ if(hres == DISP_E_UNKNOWNNAME) {
+ argv[i] = jsval_undefined();
+ }else if(FAILED(hres)) {
while(i--)
- VariantClear(argv+i);
+ jsval_release(argv[i]);
heap_free(argv);
return hres;
}
}
- args->cArgs = length;
- args->rgvarg = argv;
+ *argc = length;
+ *ret = argv;
return S_OK;
}
-static HRESULT Function_apply(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT Function_apply(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r)
{
FunctionInstance *function;
- DISPPARAMS args = {NULL,NULL,0,0};
- DWORD argc, i;
+ jsval_t *args = NULL;
+ unsigned i, cnt = 0;
IDispatch *this_obj = NULL;
HRESULT hres = S_OK;
TRACE("\n");
if(!(function = function_this(jsthis)))
- return throw_type_error(ctx, ei, IDS_NOT_FUNC, NULL);
+ return throw_type_error(ctx, JS_E_FUNCTION_EXPECTED, NULL);
- argc = arg_cnt(dp);
if(argc) {
- VARIANT *v = get_arg(dp,0);
-
- if(V_VT(v) != VT_EMPTY && V_VT(v) != VT_NULL) {
- hres = to_object(ctx, v, &this_obj);
+ if(!is_undefined(argv[0]) && !is_null(argv[0])) {
+ hres = to_object(ctx, argv[0], &this_obj);
if(FAILED(hres))
return hres;
}
}
if(argc >= 2) {
- DispatchEx *arg_array = NULL;
+ jsdisp_t *arg_array = NULL;
- if(V_VT(get_arg(dp,1)) == VT_DISPATCH) {
- arg_array = iface_to_jsdisp((IUnknown*)V_DISPATCH(get_arg(dp,1)));
+ if(is_object_instance(argv[1])) {
+ arg_array = iface_to_jsdisp((IUnknown*)get_object(argv[1]));
if(arg_array &&
(!is_class(arg_array, JSCLASS_ARRAY) && !is_class(arg_array, JSCLASS_ARGUMENTS) )) {
jsdisp_release(arg_array);
}
if(arg_array) {
- hres = array_to_args(ctx, arg_array, ei, caller, &args);
+ hres = array_to_args(ctx, arg_array, &cnt, &args);
jsdisp_release(arg_array);
}else {
FIXME("throw TypeError\n");
}
}
- hres = call_function(ctx, function, this_obj, &args, retv, ei, caller);
+ if(SUCCEEDED(hres))
+ hres = call_function(ctx, function, this_obj, cnt, args, r);
if(this_obj)
IDispatch_Release(this_obj);
- for(i=0; i<args.cArgs; i++)
- VariantClear(args.rgvarg+i);
- heap_free(args.rgvarg);
+ for(i=0; i < cnt; i++)
+ jsval_release(args[i]);
+ heap_free(args);
return hres;
}
-static HRESULT Function_call(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT Function_call(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
FunctionInstance *function;
- DISPPARAMS args = {NULL,NULL,0,0};
IDispatch *this_obj = NULL;
- DWORD argc;
+ unsigned cnt = 0;
HRESULT hres;
TRACE("\n");
if(!(function = function_this(jsthis)))
- return throw_type_error(ctx, ei, IDS_NOT_FUNC, NULL);
+ return throw_type_error(ctx, JS_E_FUNCTION_EXPECTED, NULL);
- argc = arg_cnt(dp);
if(argc) {
- VARIANT *v = get_arg(dp,0);
-
- if(V_VT(v) != VT_EMPTY && V_VT(v) != VT_NULL) {
- hres = to_object(ctx, v, &this_obj);
+ if(!is_undefined(argv[0]) && !is_null(argv[0])) {
+ hres = to_object(ctx, argv[0], &this_obj);
if(FAILED(hres))
return hres;
}
- args.cArgs = argc-1;
+ cnt = argc-1;
}
- if(args.cArgs)
- args.rgvarg = dp->rgvarg + dp->cArgs - args.cArgs-1;
-
- hres = call_function(ctx, function, this_obj, &args, retv, ei, caller);
+ hres = call_function(ctx, function, this_obj, cnt, argv+1, r);
if(this_obj)
IDispatch_Release(this_obj);
return hres;
}
-HRESULT Function_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+HRESULT Function_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
FunctionInstance *function;
switch(flags) {
case DISPATCH_METHOD:
- if(function->value_proc)
- return invoke_value_proc(ctx, function, get_this(dp), flags, dp, retv, ei, caller);
-
- return invoke_source(ctx, function, get_this(dp), dp, retv, ei, caller);
+ assert(function->value_proc != NULL);
+ return invoke_value_proc(ctx, function, NULL, flags, argc, argv, r);
case DISPATCH_PROPERTYGET: {
HRESULT hres;
- BSTR str;
+ jsstr_t *str;
hres = function_to_string(function, &str);
if(FAILED(hres))
return hres;
- V_VT(retv) = VT_BSTR;
- V_BSTR(retv) = str;
+ *r = jsval_string(str);
break;
}
case DISPATCH_CONSTRUCT:
- if(function->value_proc)
- return invoke_value_proc(ctx, function, get_this(dp), flags, dp, retv, ei, caller);
-
- return invoke_constructor(ctx, function, dp, retv, ei, caller);
+ assert(function->value_proc != NULL);
+ return invoke_value_proc(ctx, function, NULL, flags, argc, argv, r);
default:
FIXME("not implemented flags %x\n", flags);
return S_OK;
}
-static void Function_destructor(DispatchEx *dispex)
+static HRESULT Function_arguments(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
+ unsigned argc, jsval_t *argv, jsval_t *r)
+{
+ FunctionInstance *function = (FunctionInstance*)jsthis->u.jsdisp;
+ HRESULT hres = S_OK;
+
+ TRACE("\n");
+
+ switch(flags) {
+ case DISPATCH_PROPERTYGET: {
+ *r = function->arguments ? jsval_obj(jsdisp_addref(function->arguments)) : jsval_null();
+ break;
+ }
+ case DISPATCH_PROPERTYPUT:
+ break;
+ default:
+ FIXME("unimplemented flags %x\n", flags);
+ hres = E_NOTIMPL;
+ }
+
+ return hres;
+}
+
+static void Function_destructor(jsdisp_t *dispex)
{
FunctionInstance *This = (FunctionInstance*)dispex;
- if(This->parser)
- parser_release(This->parser);
+ if(This->code)
+ release_bytecode(This->code);
if(This->scope_chain)
scope_release(This->scope_chain);
heap_free(This);
static const builtin_prop_t Function_props[] = {
{applyW, Function_apply, PROPF_METHOD|2},
+ {argumentsW, Function_arguments, 0},
{callW, Function_call, PROPF_METHOD|1},
{lengthW, Function_length, 0},
{toStringW, Function_toString, PROPF_METHOD}
NULL
};
+static const builtin_prop_t FunctionInst_props[] = {
+ {argumentsW, Function_arguments, 0},
+ {lengthW, Function_length, 0}
+};
+
+static const builtin_info_t FunctionInst_info = {
+ JSCLASS_FUNCTION,
+ {NULL, Function_value, 0},
+ sizeof(FunctionInst_props)/sizeof(*FunctionInst_props),
+ FunctionInst_props,
+ Function_destructor,
+ NULL
+};
+
static HRESULT create_function(script_ctx_t *ctx, const builtin_info_t *builtin_info, DWORD flags,
- BOOL funcprot, DispatchEx *prototype, FunctionInstance **ret)
+ BOOL funcprot, jsdisp_t *prototype, FunctionInstance **ret)
{
FunctionInstance *function;
HRESULT hres;
return E_OUTOFMEMORY;
if(funcprot)
- hres = init_dispex(&function->dispex, ctx, &Function_info, prototype);
+ hres = init_dispex(&function->dispex, ctx, builtin_info, prototype);
else if(builtin_info)
hres = init_dispex_from_constr(&function->dispex, ctx, builtin_info, ctx->function_constr);
else
- hres = init_dispex_from_constr(&function->dispex, ctx, &Function_info, ctx->function_constr);
- if(FAILED(hres))
+ hres = init_dispex_from_constr(&function->dispex, ctx, &FunctionInst_info, ctx->function_constr);
+ if(FAILED(hres)) {
+ heap_free(function);
return hres;
+ }
function->flags = flags;
function->length = flags & PROPF_ARGMASK;
return S_OK;
}
-static HRESULT set_prototype(script_ctx_t *ctx, DispatchEx *dispex, DispatchEx *prototype)
+static inline HRESULT set_prototype(script_ctx_t *ctx, jsdisp_t *dispex, jsdisp_t *prototype)
{
- jsexcept_t jsexcept;
- VARIANT var;
-
- V_VT(&var) = VT_DISPATCH;
- V_DISPATCH(&var) = (IDispatch*)_IDispatchEx_(prototype);
- memset(&jsexcept, 0, sizeof(jsexcept));
-
- return jsdisp_propput_name(dispex, prototypeW, &var, &jsexcept, NULL/*FIXME*/);
+ return jsdisp_propput_dontenum(dispex, prototypeW, jsval_obj(prototype));
}
HRESULT create_builtin_function(script_ctx_t *ctx, builtin_invoke_t value_proc, const WCHAR *name,
- const builtin_info_t *builtin_info, DWORD flags, DispatchEx *prototype, DispatchEx **ret)
+ const builtin_info_t *builtin_info, DWORD flags, jsdisp_t *prototype, jsdisp_t **ret)
{
FunctionInstance *function;
HRESULT hres;
if(FAILED(hres))
return hres;
- if(builtin_info) {
- VARIANT var;
-
- V_VT(&var) = VT_I4;
- V_I4(&var) = function->length;
- hres = jsdisp_propput_const(&function->dispex, lengthW, &var);
- }
-
+ if(builtin_info)
+ hres = jsdisp_propput_const(&function->dispex, lengthW, jsval_number(function->length));
if(SUCCEEDED(hres))
hres = set_prototype(ctx, &function->dispex, prototype);
if(FAILED(hres)) {
return S_OK;
}
-HRESULT create_source_function(parser_ctx_t *ctx, parameter_t *parameters, source_elements_t *source,
- scope_chain_t *scope_chain, const WCHAR *src_str, DWORD src_len, DispatchEx **ret)
+static HRESULT set_constructor_prop(script_ctx_t *ctx, jsdisp_t *constr, jsdisp_t *prot)
+{
+ static const WCHAR constructorW[] = {'c','o','n','s','t','r','u','c','t','o','r',0};
+
+ return jsdisp_propput_dontenum(prot, constructorW, jsval_obj(constr));
+}
+
+HRESULT create_builtin_constructor(script_ctx_t *ctx, builtin_invoke_t value_proc, const WCHAR *name,
+ const builtin_info_t *builtin_info, DWORD flags, jsdisp_t *prototype, jsdisp_t **ret)
+{
+ jsdisp_t *constr;
+ HRESULT hres;
+
+ hres = create_builtin_function(ctx, value_proc, name, builtin_info, flags, prototype, &constr);
+ if(FAILED(hres))
+ return hres;
+
+ hres = set_constructor_prop(ctx, constr, prototype);
+ if(FAILED(hres)) {
+ jsdisp_release(constr);
+ return hres;
+ }
+
+ *ret = constr;
+ return S_OK;
+}
+
+HRESULT create_source_function(script_ctx_t *ctx, bytecode_t *code, function_code_t *func_code,
+ scope_chain_t *scope_chain, jsdisp_t **ret)
{
FunctionInstance *function;
- DispatchEx *prototype;
- parameter_t *iter;
- DWORD length = 0;
+ jsdisp_t *prototype;
HRESULT hres;
- hres = create_object(ctx->script, NULL, &prototype);
+ hres = create_object(ctx, NULL, &prototype);
if(FAILED(hres))
return hres;
- hres = create_function(ctx->script, NULL, PROPF_CONSTR, FALSE, NULL, &function);
+ hres = create_function(ctx, NULL, PROPF_CONSTR, FALSE, NULL, &function);
if(SUCCEEDED(hres)) {
- hres = set_prototype(ctx->script, &function->dispex, prototype);
+ hres = set_prototype(ctx, &function->dispex, prototype);
+ if(SUCCEEDED(hres))
+ hres = set_constructor_prop(ctx, &function->dispex, prototype);
if(FAILED(hres))
jsdisp_release(&function->dispex);
}
if(FAILED(hres))
return hres;
- function->source = source;
- function->parameters = parameters;
-
if(scope_chain) {
scope_addref(scope_chain);
function->scope_chain = scope_chain;
}
- parser_addref(ctx);
- function->parser = ctx;
-
- for(iter = parameters; iter; iter = iter->next)
- length++;
- function->length = length;
-
- function->src_str = src_str;
- function->src_len = src_len;
+ bytecode_addref(code);
+ function->code = code;
+ function->func_code = func_code;
+ function->length = function->func_code->param_cnt;
*ret = &function->dispex;
return S_OK;
}
-static HRESULT construct_function(script_ctx_t *ctx, DISPPARAMS *dp, jsexcept_t *ei, IDispatch **ret)
+static HRESULT construct_function(script_ctx_t *ctx, unsigned argc, jsval_t *argv, IDispatch **ret)
{
- function_expression_t *expr;
WCHAR *str = NULL, *ptr;
- DWORD argc, len = 0, l;
- parser_ctx_t *parser;
- DispatchEx *function;
- BSTR *params = NULL;
- int i=0, j=0;
+ unsigned len = 0, i = 0;
+ bytecode_t *code;
+ jsdisp_t *function;
+ jsstr_t **params = NULL;
+ int j = 0;
HRESULT hres = S_OK;
static const WCHAR function_anonymousW[] = {'f','u','n','c','t','i','o','n',' ','a','n','o','n','y','m','o','u','s','('};
static const WCHAR function_beginW[] = {')',' ','{','\n'};
static const WCHAR function_endW[] = {'\n','}',0};
- argc = arg_cnt(dp);
if(argc) {
- params = heap_alloc(argc*sizeof(BSTR));
+ params = heap_alloc(argc*sizeof(*params));
if(!params)
return E_OUTOFMEMORY;
if(argc > 2)
len = (argc-2)*2; /* separating commas */
for(i=0; i < argc; i++) {
- hres = to_string(ctx, get_arg(dp,i), ei, params+i);
+ hres = to_string(ctx, argv[i], params+i);
if(FAILED(hres))
break;
- len += SysStringLen(params[i]);
+ len += jsstr_length(params[i]);
}
}
ptr = str + sizeof(function_anonymousW)/sizeof(WCHAR);
if(argc > 1) {
while(1) {
- l = SysStringLen(params[j]);
- memcpy(ptr, params[j], l*sizeof(WCHAR));
- ptr += l;
+ ptr += jsstr_flush(params[j], ptr);
if(++j == argc-1)
break;
*ptr++ = ',';
}
memcpy(ptr, function_beginW, sizeof(function_beginW));
ptr += sizeof(function_beginW)/sizeof(WCHAR);
- if(argc) {
- l = SysStringLen(params[argc-1]);
- memcpy(ptr, params[argc-1], l*sizeof(WCHAR));
- ptr += l;
- }
+ if(argc)
+ ptr += jsstr_flush(params[argc-1], ptr);
memcpy(ptr, function_endW, sizeof(function_endW));
TRACE("%s\n", debugstr_w(str));
}
}
- while(--i >= 0)
- SysFreeString(params[i]);
+ while(i)
+ jsstr_release(params[--i]);
heap_free(params);
if(FAILED(hres))
return hres;
- hres = script_parse(ctx, str, NULL, &parser);
+ hres = compile_script(ctx, str, NULL, NULL, FALSE, FALSE, &code);
heap_free(str);
if(FAILED(hres))
return hres;
- if(!parser->source || !parser->source->functions || parser->source->functions->next || parser->source->variables) {
+ if(code->global_code.func_cnt != 1 || code->global_code.var_cnt) {
ERR("Invalid parser result!\n");
- parser_release(parser);
+ release_bytecode(code);
return E_UNEXPECTED;
}
- expr = parser->source->functions->expr;
- hres = create_source_function(parser, expr->parameter_list, expr->source_elements, NULL, expr->src_str,
- expr->src_len, &function);
- parser_release(parser);
+ hres = create_source_function(ctx, code, code->global_code.funcs, NULL, &function);
+ release_bytecode(code);
if(FAILED(hres))
return hres;
- *ret = (IDispatch*)_IDispatchEx_(function);
+ *ret = to_disp(function);
return S_OK;
}
-static HRESULT FunctionConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT FunctionConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
HRESULT hres;
case DISPATCH_CONSTRUCT: {
IDispatch *ret;
- hres = construct_function(ctx, dp, ei, &ret);
+ hres = construct_function(ctx, argc, argv, &ret);
if(FAILED(hres))
return hres;
- V_VT(retv) = VT_DISPATCH;
- V_DISPATCH(retv) = ret;
+ *r = jsval_disp(ret);
break;
}
default:
return S_OK;
}
-static HRESULT FunctionProt_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT FunctionProt_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
FIXME("\n");
return E_NOTIMPL;
}
-HRESULT init_function_constr(script_ctx_t *ctx, DispatchEx *object_prototype)
+HRESULT init_function_constr(script_ctx_t *ctx, jsdisp_t *object_prototype)
{
FunctionInstance *prot, *constr;
HRESULT hres;
static const WCHAR FunctionW[] = {'F','u','n','c','t','i','o','n',0};
- hres = create_function(ctx, NULL, PROPF_CONSTR, TRUE, object_prototype, &prot);
+ hres = create_function(ctx, &Function_info, PROPF_CONSTR, TRUE, object_prototype, &prot);
if(FAILED(hres))
return hres;
prot->value_proc = FunctionProt_value;
prot->name = prototypeW;
- hres = create_function(ctx, NULL, PROPF_CONSTR|1, TRUE, &prot->dispex, &constr);
+ hres = create_function(ctx, &FunctionInst_info, PROPF_CONSTR|1, TRUE, &prot->dispex, &constr);
if(SUCCEEDED(hres)) {
constr->value_proc = FunctionConstr_value;
constr->name = FunctionW;
hres = set_prototype(ctx, &constr->dispex, &prot->dispex);
+ if(SUCCEEDED(hres))
+ hres = set_constructor_prop(ctx, &constr->dispex, &prot->dispex);
if(FAILED(hres))
jsdisp_release(&constr->dispex);
}
static const WCHAR ObjectW[] = {'O','b','j','e','c','t',0};
static const WCHAR StringW[] = {'S','t','r','i','n','g',0};
static const WCHAR RegExpW[] = {'R','e','g','E','x','p',0};
+static const WCHAR RegExpErrorW[] = {'R','e','g','E','x','p','E','r','r','o','r',0};
static const WCHAR ActiveXObjectW[] = {'A','c','t','i','v','e','X','O','b','j','e','c','t',0};
static const WCHAR VBArrayW[] = {'V','B','A','r','r','a','y',0};
static const WCHAR EnumeratorW[] = {'E','n','u','m','e','r','a','t','o','r',0};
return c < 128 && uri_char_table[c] == 2;
}
+/* Check that the character is one of the 69 non-blank characters as defined by ECMA-262 B.2.1 */
+static inline BOOL is_ecma_nonblank(const WCHAR c)
+{
+ return ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') ||
+ c == '@' || c == '*' || c == '_' || c == '+' || c == '-' || c == '.' || c == '/');
+}
+
static WCHAR int_to_char(int i)
{
if(i < 10)
return 'A'+i-10;
}
-static HRESULT constructor_call(DispatchEx *constr, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT constructor_call(jsdisp_t *constr, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r)
{
if(flags != DISPATCH_PROPERTYGET)
- return jsdisp_call_value(constr, flags, dp, retv, ei, sp);
+ return jsdisp_call_value(constr, NULL, flags, argc, argv, r);
- V_VT(retv) = VT_DISPATCH;
- V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(constr);
- IDispatchEx_AddRef(_IDispatchEx_(constr));
+ *r = jsval_obj(jsdisp_addref(constr));
return S_OK;
}
-static HRESULT JSGlobal_NaN(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT JSGlobal_Array(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
TRACE("\n");
- switch(flags) {
- case DISPATCH_PROPERTYGET:
- num_set_nan(retv);
- break;
-
- default:
- FIXME("unimplemented flags %x\n", flags);
- return E_NOTIMPL;
- }
-
- return S_OK;
+ return constructor_call(ctx->array_constr, flags, argc, argv, r);
}
-static HRESULT JSGlobal_Infinity(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT JSGlobal_Boolean(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
TRACE("\n");
- switch(flags) {
- case DISPATCH_PROPERTYGET:
- num_set_inf(retv, TRUE);
- break;
-
- default:
- FIXME("unimplemented flags %x\n", flags);
- return E_NOTIMPL;
- }
-
- return S_OK;
+ return constructor_call(ctx->bool_constr, flags, argc, argv, r);
}
-static HRESULT JSGlobal_Array(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT JSGlobal_Date(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
TRACE("\n");
- return constructor_call(ctx->array_constr, flags, dp, retv, ei, sp);
+ return constructor_call(ctx->date_constr, flags, argc, argv, r);
}
-static HRESULT JSGlobal_Boolean(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT JSGlobal_Error(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
TRACE("\n");
- return constructor_call(ctx->bool_constr, flags, dp, retv, ei, sp);
+ return constructor_call(ctx->error_constr, flags, argc, argv, r);
}
-static HRESULT JSGlobal_Date(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT JSGlobal_EvalError(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
TRACE("\n");
- return constructor_call(ctx->date_constr, flags, dp, retv, ei, sp);
+ return constructor_call(ctx->eval_error_constr, flags, argc, argv, r);
}
-static HRESULT JSGlobal_Error(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT JSGlobal_RangeError(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
TRACE("\n");
- return constructor_call(ctx->error_constr, flags, dp, retv, ei, sp);
+ return constructor_call(ctx->range_error_constr, flags, argc, argv, r);
}
-static HRESULT JSGlobal_EvalError(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT JSGlobal_RegExpError(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
TRACE("\n");
- return constructor_call(ctx->eval_error_constr, flags, dp, retv, ei, sp);
+ return constructor_call(ctx->regexp_error_constr, flags, argc, argv, r);
}
-static HRESULT JSGlobal_RangeError(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT JSGlobal_ReferenceError(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
TRACE("\n");
- return constructor_call(ctx->range_error_constr, flags, dp, retv, ei, sp);
+ return constructor_call(ctx->reference_error_constr, flags, argc, argv, r);
}
-static HRESULT JSGlobal_ReferenceError(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT JSGlobal_SyntaxError(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
TRACE("\n");
- return constructor_call(ctx->reference_error_constr, flags, dp, retv, ei, sp);
+ return constructor_call(ctx->syntax_error_constr, flags, argc, argv, r);
}
-static HRESULT JSGlobal_SyntaxError(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT JSGlobal_TypeError(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
TRACE("\n");
- return constructor_call(ctx->syntax_error_constr, flags, dp, retv, ei, sp);
+ return constructor_call(ctx->type_error_constr, flags, argc, argv, r);
}
-static HRESULT JSGlobal_TypeError(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT JSGlobal_URIError(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
TRACE("\n");
- return constructor_call(ctx->type_error_constr, flags, dp, retv, ei, sp);
+ return constructor_call(ctx->uri_error_constr, flags, argc, argv, r);
}
-static HRESULT JSGlobal_URIError(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT JSGlobal_Function(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
TRACE("\n");
- return constructor_call(ctx->uri_error_constr, flags, dp, retv, ei, sp);
+ return constructor_call(ctx->function_constr, flags, argc, argv, r);
}
-static HRESULT JSGlobal_Function(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT JSGlobal_Number(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
TRACE("\n");
- return constructor_call(ctx->function_constr, flags, dp, retv, ei, sp);
+ return constructor_call(ctx->number_constr, flags, argc, argv, r);
}
-static HRESULT JSGlobal_Number(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT JSGlobal_Object(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
TRACE("\n");
- return constructor_call(ctx->number_constr, flags, dp, retv, ei, sp);
+ return constructor_call(ctx->object_constr, flags, argc, argv, r);
}
-static HRESULT JSGlobal_Object(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT JSGlobal_String(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
TRACE("\n");
- return constructor_call(ctx->object_constr, flags, dp, retv, ei, sp);
+ return constructor_call(ctx->string_constr, flags, argc, argv, r);
}
-static HRESULT JSGlobal_String(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT JSGlobal_RegExp(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
TRACE("\n");
- return constructor_call(ctx->string_constr, flags, dp, retv, ei, sp);
+ return constructor_call(ctx->regexp_constr, flags, argc, argv, r);
}
-static HRESULT JSGlobal_RegExp(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT JSGlobal_ActiveXObject(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
TRACE("\n");
- return constructor_call(ctx->regexp_constr, flags, dp, retv, ei, sp);
+ return constructor_call(ctx->activex_constr, flags, argc, argv, r);
}
-static HRESULT JSGlobal_ActiveXObject(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT JSGlobal_VBArray(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
TRACE("\n");
- return constructor_call(ctx->activex_constr, flags, dp, retv, ei, sp);
-}
-
-static HRESULT JSGlobal_VBArray(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
-{
- FIXME("\n");
- return E_NOTIMPL;
+ return constructor_call(ctx->vbarray_constr, flags, argc, argv, r);
}
-static HRESULT JSGlobal_Enumerator(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT JSGlobal_Enumerator(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
FIXME("\n");
return E_NOTIMPL;
}
-static HRESULT JSGlobal_escape(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT JSGlobal_escape(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- BSTR ret, str;
+ jsstr_t *ret_str, *str;
const WCHAR *ptr;
DWORD len = 0;
+ WCHAR *ret;
HRESULT hres;
TRACE("\n");
- if(!arg_cnt(dp)) {
- if(retv) {
- ret = SysAllocString(undefinedW);
- if(!ret)
- return E_OUTOFMEMORY;
-
- V_VT(retv) = VT_BSTR;
- V_BSTR(retv) = ret;
- }
-
+ if(!argc) {
+ if(r)
+ *r = jsval_string(jsstr_undefined());
return S_OK;
}
- hres = to_string(ctx, get_arg(dp, 0), ei, &str);
+ hres = to_string(ctx, argv[0], &str);
if(FAILED(hres))
return hres;
- for(ptr=str; *ptr; ptr++) {
+ for(ptr = str->str; *ptr; ptr++) {
if(*ptr > 0xff)
len += 6;
- else if(isalnum((char)*ptr) || *ptr=='*' || *ptr=='@' || *ptr=='-'
- || *ptr=='_' || *ptr=='+' || *ptr=='.' || *ptr=='/')
+ else if(is_ecma_nonblank(*ptr))
len++;
else
len += 3;
}
- ret = SysAllocStringLen(NULL, len);
- if(!ret) {
- SysFreeString(str);
+ ret_str = jsstr_alloc_buf(len);
+ if(!ret_str) {
+ jsstr_release(str);
return E_OUTOFMEMORY;
}
len = 0;
- for(ptr=str; *ptr; ptr++) {
+ ret = ret_str->str;
+ for(ptr = str->str; *ptr; ptr++) {
if(*ptr > 0xff) {
ret[len++] = '%';
ret[len++] = 'u';
ret[len++] = int_to_char((*ptr >> 4) & 0xf);
ret[len++] = int_to_char(*ptr & 0xf);
}
- else if(isalnum((char)*ptr) || *ptr=='*' || *ptr=='@' || *ptr=='-'
- || *ptr=='_' || *ptr=='+' || *ptr=='.' || *ptr=='/')
+ else if(is_ecma_nonblank(*ptr))
ret[len++] = *ptr;
else {
ret[len++] = '%';
}
}
- SysFreeString(str);
+ jsstr_release(str);
- if(retv) {
- V_VT(retv) = VT_BSTR;
- V_BSTR(retv) = ret;
- }
+ if(r)
+ *r = jsval_string(ret_str);
else
- SysFreeString(ret);
-
+ jsstr_release(ret_str);
return S_OK;
}
/* ECMA-262 3rd Edition 15.1.2.1 */
-static HRESULT JSGlobal_eval(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT JSGlobal_eval(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- parser_ctx_t *parser_ctx;
- VARIANT *arg;
+ bytecode_t *code;
HRESULT hres;
TRACE("\n");
- if(!arg_cnt(dp)) {
- if(retv)
- V_VT(retv) = VT_EMPTY;
+ if(!argc) {
+ if(r)
+ *r = jsval_undefined();
return S_OK;
}
- arg = get_arg(dp, 0);
- if(V_VT(arg) != VT_BSTR) {
- if(retv) {
- V_VT(retv) = VT_EMPTY;
- return VariantCopy(retv, arg);
- }
+ if(!is_string(argv[0])) {
+ if(r)
+ return jsval_copy(argv[0], r);
return S_OK;
}
return E_UNEXPECTED;
}
- TRACE("parsing %s\n", debugstr_w(V_BSTR(arg)));
- hres = script_parse(ctx, V_BSTR(arg), NULL, &parser_ctx);
+ TRACE("parsing %s\n", debugstr_jsval(argv[0]));
+ hres = compile_script(ctx, get_string(argv[0])->str, NULL, NULL, TRUE, FALSE, &code);
if(FAILED(hres)) {
- WARN("parse (%s) failed: %08x\n", debugstr_w(V_BSTR(arg)), hres);
- return throw_syntax_error(ctx, ei, hres, NULL);
+ WARN("parse (%s) failed: %08x\n", debugstr_jsval(argv[0]), hres);
+ return throw_syntax_error(ctx, hres, NULL);
}
- hres = exec_source(ctx->exec_ctx, parser_ctx, parser_ctx->source, EXECT_EVAL, ei, retv);
- parser_release(parser_ctx);
-
+ hres = exec_source(ctx->exec_ctx, code, &code->global_code, TRUE, r);
+ release_bytecode(code);
return hres;
}
-static HRESULT JSGlobal_isNaN(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT JSGlobal_isNaN(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- VARIANT_BOOL ret = VARIANT_FALSE;
- VARIANT num;
+ BOOL ret = TRUE;
+ double n;
HRESULT hres;
TRACE("\n");
- if(arg_cnt(dp)) {
- hres = to_number(ctx, get_arg(dp,0), ei, &num);
+ if(argc) {
+ hres = to_number(ctx, argv[0], &n);
if(FAILED(hres))
return hres;
- if(V_VT(&num) == VT_R8 && isnan(V_R8(&num)))
- ret = VARIANT_TRUE;
- }else {
- ret = VARIANT_TRUE;
+ if(!isnan(n))
+ ret = FALSE;
}
- if(retv) {
- V_VT(retv) = VT_BOOL;
- V_BOOL(retv) = ret;
- }
+ if(r)
+ *r = jsval_bool(ret);
return S_OK;
}
-static HRESULT JSGlobal_isFinite(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT JSGlobal_isFinite(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- VARIANT_BOOL ret = VARIANT_FALSE;
+ BOOL ret = FALSE;
HRESULT hres;
TRACE("\n");
- if(arg_cnt(dp)) {
- VARIANT num;
+ if(argc) {
+ double n;
- hres = to_number(ctx, get_arg(dp,0), ei, &num);
+ hres = to_number(ctx, argv[0], &n);
if(FAILED(hres))
return hres;
- if(V_VT(&num) != VT_R8 || (!isinf(V_R8(&num)) && !isnan(V_R8(&num))))
- ret = VARIANT_TRUE;
+ if(!isinf(n) && !isnan(n))
+ ret = TRUE;
}
- if(retv) {
- V_VT(retv) = VT_BOOL;
- V_BOOL(retv) = ret;
- }
+ if(r)
+ *r = jsval_bool(ret);
return S_OK;
}
return 100;
}
-static HRESULT JSGlobal_parseInt(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT JSGlobal_parseInt(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
+ BOOL neg = FALSE, empty = TRUE;
DOUBLE ret = 0.0;
- INT radix=10, i;
+ INT radix=0, i;
+ jsstr_t *str;
WCHAR *ptr;
- BOOL neg = FALSE;
- BSTR str;
HRESULT hres;
- if(!arg_cnt(dp)) {
- if(retv) num_set_nan(retv);
+ if(!argc) {
+ if(r)
+ *r = jsval_number(NAN);
return S_OK;
}
- if(arg_cnt(dp) >= 2) {
- hres = to_int32(ctx, get_arg(dp, 1), ei, &radix);
+ if(argc >= 2) {
+ hres = to_int32(ctx, argv[1], &radix);
if(FAILED(hres))
return hres;
- if(!radix) {
- radix = 10;
- }else if(radix < 2 || radix > 36) {
+ if(radix && (radix < 2 || radix > 36)) {
WARN("radix %d out of range\n", radix);
- return E_FAIL;
+ if(r)
+ *r = jsval_number(NAN);
+ return S_OK;
}
}
- hres = to_string(ctx, get_arg(dp, 0), ei, &str);
+ hres = to_string(ctx, argv[0], &str);
if(FAILED(hres))
return hres;
- for(ptr = str; isspaceW(*ptr); ptr++);
+ for(ptr = str->str; isspaceW(*ptr); ptr++);
switch(*ptr) {
case '+':
neg = TRUE;
ptr++;
break;
- case '0':
- ptr++;
- if(*ptr == 'x' || *ptr == 'X') {
- radix = 16;
- ptr++;
- }
}
- while(*ptr) {
- i = char_to_int(*ptr++);
- if(i > radix)
- break;
+ if(!radix) {
+ if(*ptr == '0') {
+ if(ptr[1] == 'x' || ptr[1] == 'X') {
+ radix = 16;
+ ptr += 2;
+ }else {
+ radix = 8;
+ ptr++;
+ empty = FALSE;
+ }
+ }else {
+ radix = 10;
+ }
+ }
- ret = ret*radix + i;
+ i = char_to_int(*ptr++);
+ if(i < radix) {
+ do {
+ ret = ret*radix + i;
+ i = char_to_int(*ptr++);
+ }while(i < radix);
+ }else if(empty) {
+ ret = NAN;
}
- SysFreeString(str);
+ jsstr_release(str);
if(neg)
ret = -ret;
- if(retv)
- num_set_val(retv, ret);
+ if(r)
+ *r = jsval_number(ret);
return S_OK;
}
-static HRESULT JSGlobal_parseFloat(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT JSGlobal_parseFloat(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
LONGLONG d = 0, hlp;
+ jsstr_t *val_str;
int exp = 0;
- VARIANT *arg;
WCHAR *str;
- BSTR val_str = NULL;
BOOL ret_nan = TRUE, positive = TRUE;
HRESULT hres;
- if(!arg_cnt(dp)) {
- if(retv)
- num_set_nan(retv);
+ if(!argc) {
+ if(r)
+ *r = jsval_number(NAN);
return S_OK;
}
- arg = get_arg(dp, 0);
- hres = to_string(ctx, arg, ei, &val_str);
+ hres = to_string(ctx, argv[0], &val_str);
if(FAILED(hres))
return hres;
- str = val_str;
+ str = val_str->str;
while(isspaceW(*str)) str++;
else exp += e;
}
- SysFreeString(val_str);
+ jsstr_release(val_str);
if(ret_nan) {
- if(retv)
- num_set_nan(retv);
+ if(r)
+ *r = jsval_number(NAN);
return S_OK;
}
- V_VT(retv) = VT_R8;
- V_R8(retv) = (double)(positive?d:-d)*pow(10, exp);
+ if(!positive)
+ d = -d;
+ if(r)
+ *r = jsval_number(exp>0 ? d*pow(10, exp) : d/pow(10, -exp));
return S_OK;
}
return -1;
}
-static HRESULT JSGlobal_unescape(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT JSGlobal_unescape(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- BSTR ret, str;
+ jsstr_t *ret_str, *str;
const WCHAR *ptr;
DWORD len = 0;
+ WCHAR *ret;
HRESULT hres;
TRACE("\n");
- if(!arg_cnt(dp)) {
- if(retv) {
- ret = SysAllocString(undefinedW);
- if(!ret)
- return E_OUTOFMEMORY;
-
- V_VT(retv) = VT_BSTR;
- V_BSTR(retv) = ret;
- }
-
+ if(!argc) {
+ if(r)
+ *r = jsval_string(jsstr_undefined());
return S_OK;
}
- hres = to_string(ctx, get_arg(dp, 0), ei, &str);
+ hres = to_string(ctx, argv[0], &str);
if(FAILED(hres))
return hres;
- for(ptr=str; *ptr; ptr++) {
+ for(ptr = str->str; *ptr; ptr++) {
if(*ptr == '%') {
if(hex_to_int(*(ptr+1))!=-1 && hex_to_int(*(ptr+2))!=-1)
ptr += 2;
len++;
}
- ret = SysAllocStringLen(NULL, len);
- if(!ret) {
- SysFreeString(str);
+ ret_str = jsstr_alloc_buf(len);
+ if(!ret_str) {
+ jsstr_release(str);
return E_OUTOFMEMORY;
}
+ ret = ret_str->str;
len = 0;
- for(ptr=str; *ptr; ptr++) {
+ for(ptr = str->str; *ptr; ptr++) {
if(*ptr == '%') {
if(hex_to_int(*(ptr+1))!=-1 && hex_to_int(*(ptr+2))!=-1) {
ret[len] = (hex_to_int(*(ptr+1))<<4) + hex_to_int(*(ptr+2));
len++;
}
- SysFreeString(str);
+ jsstr_release(str);
- if(retv) {
- V_VT(retv) = VT_BSTR;
- V_BSTR(retv) = ret;
- }
+ if(r)
+ *r = jsval_string(ret_str);
else
- SysFreeString(ret);
-
+ jsstr_release(ret_str);
return S_OK;
}
-static HRESULT JSGlobal_GetObject(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT JSGlobal_GetObject(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
FIXME("\n");
return E_NOTIMPL;
}
-static HRESULT JSGlobal_ScriptEngine(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT JSGlobal_ScriptEngine(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- FIXME("\n");
- return E_NOTIMPL;
+ static const WCHAR JScriptW[] = {'J','S','c','r','i','p','t',0};
+
+ TRACE("\n");
+
+ if(r) {
+ jsstr_t *ret;
+
+ ret = jsstr_alloc(JScriptW);
+ if(!ret)
+ return E_OUTOFMEMORY;
+
+ *r = jsval_string(ret);
+ }
+
+ return S_OK;
}
-static HRESULT JSGlobal_ScriptEngineMajorVersion(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT JSGlobal_ScriptEngineMajorVersion(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- FIXME("\n");
- return E_NOTIMPL;
+ TRACE("\n");
+
+ if(r)
+ *r = jsval_number(JSCRIPT_MAJOR_VERSION);
+ return S_OK;
}
-static HRESULT JSGlobal_ScriptEngineMinorVersion(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT JSGlobal_ScriptEngineMinorVersion(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- FIXME("\n");
- return E_NOTIMPL;
+ TRACE("\n");
+
+ if(r)
+ *r = jsval_number(JSCRIPT_MINOR_VERSION);
+ return S_OK;
}
-static HRESULT JSGlobal_ScriptEngineBuildVersion(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT JSGlobal_ScriptEngineBuildVersion(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- FIXME("\n");
- return E_NOTIMPL;
+ TRACE("\n");
+
+ if(r)
+ *r = jsval_number(JSCRIPT_BUILD_VERSION);
+ return S_OK;
}
-static HRESULT JSGlobal_CollectGarbage(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT JSGlobal_CollectGarbage(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
FIXME("\n");
return E_NOTIMPL;
}
-static HRESULT JSGlobal_encodeURI(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT JSGlobal_encodeURI(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
+ jsstr_t *str, *ret;
const WCHAR *ptr;
DWORD len = 0, i;
char buf[4];
- BSTR str, ret;
WCHAR *rptr;
HRESULT hres;
TRACE("\n");
- if(!arg_cnt(dp)) {
- if(retv) {
- ret = SysAllocString(undefinedW);
- if(!ret)
- return E_OUTOFMEMORY;
-
- V_VT(retv) = VT_BSTR;
- V_BSTR(retv) = ret;
- }
-
+ if(!argc) {
+ if(r)
+ *r = jsval_string(jsstr_undefined());
return S_OK;
}
- hres = to_string(ctx, get_arg(dp,0), ei, &str);
+ hres = to_string(ctx, argv[0], &str);
if(FAILED(hres))
return hres;
- for(ptr = str; *ptr; ptr++) {
+ for(ptr = str->str; *ptr; ptr++) {
if(is_uri_unescaped(*ptr) || is_uri_reserved(*ptr) || *ptr == '#') {
len++;
}else {
i = WideCharToMultiByte(CP_UTF8, 0, ptr, 1, NULL, 0, NULL, NULL)*3;
if(!i) {
- SysFreeString(str);
- return throw_uri_error(ctx, ei, IDS_URI_INVALID_CHAR, NULL);
+ jsstr_release(str);
+ return throw_uri_error(ctx, JS_E_INVALID_URI_CHAR, NULL);
}
len += i;
}
}
- rptr = ret = SysAllocStringLen(NULL, len);
+ ret = jsstr_alloc_buf(len);
if(!ret) {
- SysFreeString(str);
+ jsstr_release(str);
return E_OUTOFMEMORY;
}
+ rptr = ret->str;
- for(ptr = str; *ptr; ptr++) {
+ for(ptr = str->str; *ptr; ptr++) {
if(is_uri_unescaped(*ptr) || is_uri_reserved(*ptr) || *ptr == '#') {
*rptr++ = *ptr;
}else {
}
}
- SysFreeString(str);
+ TRACE("%s -> %s\n", debugstr_jsstr(str), debugstr_jsstr(ret));
+ jsstr_release(str);
- TRACE("%s -> %s\n", debugstr_w(str), debugstr_w(ret));
- if(retv) {
- V_VT(retv) = VT_BSTR;
- V_BSTR(retv) = ret;
- }else {
- SysFreeString(ret);
- }
+ if(r)
+ *r = jsval_string(ret);
+ else
+ jsstr_release(ret);
return S_OK;
}
-static HRESULT JSGlobal_decodeURI(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT JSGlobal_decodeURI(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- FIXME("\n");
- return E_NOTIMPL;
+ jsstr_t *str, *ret;
+ WCHAR *ptr;
+ int i, len = 0, val, res;
+ char buf[4];
+ WCHAR out;
+ HRESULT hres;
+
+ TRACE("\n");
+
+ if(!argc) {
+ if(r)
+ *r = jsval_string(jsstr_undefined());
+ return S_OK;
+ }
+
+ hres = to_string(ctx, argv[0], &str);
+ if(FAILED(hres))
+ return hres;
+
+ for(ptr = str->str; *ptr; ptr++) {
+ if(*ptr != '%') {
+ len++;
+ }else {
+ res = 0;
+ 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)
+ break;
+ val += hex_to_int(ptr[i*3+1])<<4;
+ buf[i] = val;
+
+ res = MultiByteToWideChar(CP_UTF8, 0, buf, i+1, &out, 1);
+ if(res)
+ break;
+ }
+
+ if(!res) {
+ jsstr_release(str);
+ return throw_uri_error(ctx, JS_E_INVALID_URI_CODING, NULL);
+ }
+
+ ptr += i*3+2;
+ len++;
+ }
+ }
+
+ ret = jsstr_alloc_buf(len);
+ if(!ret) {
+ jsstr_release(str);
+ return E_OUTOFMEMORY;
+ }
+
+ len = 0;
+ for(ptr = str->str; *ptr; ptr++) {
+ if(*ptr != '%') {
+ ret->str[len] = *ptr;
+ len++;
+ }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)
+ break;
+ val += hex_to_int(ptr[i*3+1])<<4;
+ buf[i] = val;
+
+ res = MultiByteToWideChar(CP_UTF8, 0, buf, i+1, ret->str+len, 1);
+ if(res)
+ break;
+ }
+
+ ptr += i*3+2;
+ len++;
+ }
+ }
+
+ TRACE("%s -> %s\n", debugstr_jsstr(str), debugstr_jsstr(ret));
+ jsstr_release(str);
+
+ if(r)
+ *r = jsval_string(ret);
+ else
+ jsstr_release(ret);
+ return S_OK;
}
-static HRESULT JSGlobal_encodeURIComponent(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT JSGlobal_encodeURIComponent(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- BSTR str, ret;
+ jsstr_t *str, *ret;
char buf[4];
const WCHAR *ptr;
DWORD len = 0, size, i;
TRACE("\n");
- if(!arg_cnt(dp)) {
- if(retv) {
- ret = SysAllocString(undefinedW);
- if(!ret)
- return E_OUTOFMEMORY;
-
- V_VT(retv) = VT_BSTR;
- V_BSTR(retv) = ret;
- }
-
+ if(!argc) {
+ if(r)
+ *r = jsval_string(jsstr_undefined());
return S_OK;
}
- hres = to_string(ctx, get_arg(dp, 0), ei, &str);
+ hres = to_string(ctx, argv[0], &str);
if(FAILED(hres))
return hres;
- for(ptr=str; *ptr; ptr++) {
+ for(ptr = str->str; *ptr; ptr++) {
if(is_uri_unescaped(*ptr))
len++;
else {
size = WideCharToMultiByte(CP_UTF8, 0, ptr, 1, NULL, 0, NULL, NULL);
if(!size) {
- SysFreeString(str);
- FIXME("throw Error\n");
- return E_FAIL;
+ jsstr_release(str);
+ return throw_uri_error(ctx, JS_E_INVALID_URI_CHAR, NULL);
}
len += size*3;
}
}
- ret = SysAllocStringLen(NULL, len);
+ ret = jsstr_alloc_buf(len);
if(!ret) {
- SysFreeString(str);
+ jsstr_release(str);
return E_OUTOFMEMORY;
}
len = 0;
- for(ptr=str; *ptr; ptr++) {
- if(is_uri_unescaped(*ptr))
- ret[len++] = *ptr;
- else {
+ for(ptr = str->str; *ptr; ptr++) {
+ if(is_uri_unescaped(*ptr)) {
+ ret->str[len++] = *ptr;
+ }else {
size = WideCharToMultiByte(CP_UTF8, 0, ptr, 1, buf, sizeof(buf), NULL, NULL);
for(i=0; i<size; i++) {
- ret[len++] = '%';
- ret[len++] = int_to_char((BYTE)buf[i] >> 4);
- ret[len++] = int_to_char(buf[i] & 0x0f);
+ ret->str[len++] = '%';
+ ret->str[len++] = int_to_char((BYTE)buf[i] >> 4);
+ ret->str[len++] = int_to_char(buf[i] & 0x0f);
}
}
}
- SysFreeString(str);
-
- if(retv) {
- V_VT(retv) = VT_BSTR;
- V_BSTR(retv) = ret;
- } else {
- SysFreeString(ret);
- }
+ jsstr_release(str);
+ if(r)
+ *r = jsval_string(ret);
+ else
+ jsstr_release(ret);
return S_OK;
}
/* ECMA-262 3rd Edition 15.1.3.2 */
-static HRESULT JSGlobal_decodeURIComponent(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT JSGlobal_decodeURIComponent(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- BSTR str, ret;
+ jsstr_t *str, *ret;
const WCHAR *ptr;
WCHAR *out_ptr;
DWORD len = 0;
TRACE("\n");
- if(!arg_cnt(dp)) {
- if(retv) {
- ret = SysAllocString(undefinedW);
- if(!ret)
- return E_OUTOFMEMORY;
-
- V_VT(retv) = VT_BSTR;
- V_BSTR(retv) = ret;
- }
-
+ if(!argc) {
+ if(r)
+ *r = jsval_string(jsstr_undefined());
return S_OK;
}
- hres = to_string(ctx, get_arg(dp, 0), ei, &str);
+ hres = to_string(ctx, argv[0], &str);
if(FAILED(hres))
return hres;
- ptr = str;
+ ptr = str->str;
while(*ptr) {
if(*ptr == '%') {
char octets[4];
int i, size, num_bytes = 0;
if(hex_to_int(*(ptr+1)) < 0 || hex_to_int(*(ptr+2)) < 0) {
FIXME("Throw URIError: Invalid hex sequence\n");
- SysFreeString(str);
+ jsstr_release(str);
return E_FAIL;
}
octets[0] = (hex_to_int(*(ptr+1)) << 4) + hex_to_int(*(ptr+2));
}
if(num_bytes == 1 || num_bytes > 4) {
FIXME("Throw URIError: Invalid initial UTF character\n");
- SysFreeString(str);
+ jsstr_release(str);
return E_FAIL;
}
for(i = 1; i < num_bytes; ++i) {
if(*ptr != '%'){
FIXME("Throw URIError: Incomplete UTF sequence\n");
- SysFreeString(str);
+ jsstr_release(str);
return E_FAIL;
}
if(hex_to_int(*(ptr+1)) < 0 || hex_to_int(*(ptr+2)) < 0) {
FIXME("Throw URIError: Invalid hex sequence\n");
- SysFreeString(str);
+ jsstr_release(str);
return E_FAIL;
}
octets[i] = (hex_to_int(*(ptr+1)) << 4) + hex_to_int(*(ptr+2));
num_bytes ? num_bytes : 1, NULL, 0);
if(size == 0) {
FIXME("Throw URIError: Invalid UTF sequence\n");
- SysFreeString(str);
+ jsstr_release(str);
return E_FAIL;
}
len += size;
}
}
- out_ptr = ret = SysAllocStringLen(NULL, len);
+ ret = jsstr_alloc_buf(len);
if(!ret) {
- SysFreeString(str);
+ jsstr_release(str);
return E_OUTOFMEMORY;
}
+ out_ptr = ret->str;
- ptr = str;
+ ptr = str->str;
while(*ptr) {
if(*ptr == '%') {
char octets[4];
}
}
- SysFreeString(str);
-
- if(retv) {
- V_VT(retv) = VT_BSTR;
- V_BSTR(retv) = ret;
- }else {
- SysFreeString(ret);
- }
+ jsstr_release(str);
+ if(r)
+ *r = jsval_string(ret);
+ else
+ jsstr_release(ret);
return S_OK;
}
{EvalErrorW, JSGlobal_EvalError, PROPF_CONSTR|1},
{FunctionW, JSGlobal_Function, PROPF_CONSTR|1},
{_GetObjectW, JSGlobal_GetObject, PROPF_METHOD|2},
- {InfinityW, JSGlobal_Infinity, 0},
-/* {MathW, JSGlobal_Math, 0}, */
- {NaNW, JSGlobal_NaN, 0},
{NumberW, JSGlobal_Number, PROPF_CONSTR|1},
{ObjectW, JSGlobal_Object, PROPF_CONSTR|1},
{RangeErrorW, JSGlobal_RangeError, PROPF_CONSTR|1},
{ReferenceErrorW, JSGlobal_ReferenceError, PROPF_CONSTR|1},
{RegExpW, JSGlobal_RegExp, PROPF_CONSTR|2},
+ {RegExpErrorW, JSGlobal_RegExpError, PROPF_CONSTR|1},
{ScriptEngineW, JSGlobal_ScriptEngine, PROPF_METHOD},
{ScriptEngineBuildVersionW, JSGlobal_ScriptEngineBuildVersion, PROPF_METHOD},
{ScriptEngineMajorVersionW, JSGlobal_ScriptEngineMajorVersion, PROPF_METHOD},
{SyntaxErrorW, JSGlobal_SyntaxError, PROPF_CONSTR|1},
{TypeErrorW, JSGlobal_TypeError, PROPF_CONSTR|1},
{URIErrorW, JSGlobal_URIError, PROPF_CONSTR|1},
- {VBArrayW, JSGlobal_VBArray, PROPF_METHOD|1},
+ {VBArrayW, JSGlobal_VBArray, PROPF_CONSTR|1},
{decodeURIW, JSGlobal_decodeURI, PROPF_METHOD|1},
{decodeURIComponentW, JSGlobal_decodeURIComponent, PROPF_METHOD|1},
{encodeURIW, JSGlobal_encodeURI, PROPF_METHOD|1},
NULL
};
-static HRESULT init_constructors(script_ctx_t *ctx, DispatchEx *object_prototype)
+static HRESULT init_constructors(script_ctx_t *ctx, jsdisp_t *object_prototype)
{
HRESULT hres;
if(FAILED(hres))
return hres;
+ hres = create_vbarray_constr(ctx, object_prototype, &ctx->vbarray_constr);
+ if(FAILED(hres))
+ return hres;
+
return S_OK;
}
HRESULT init_global(script_ctx_t *ctx)
{
- DispatchEx *math, *object_prototype;
- VARIANT var;
+ jsdisp_t *math, *object_prototype;
HRESULT hres;
if(ctx->global)
if(FAILED(hres))
return hres;
- V_VT(&var) = VT_EMPTY;
- hres = jsdisp_propput_name(ctx->global, undefinedW, &var, NULL/*FIXME*/, NULL/*FIXME*/);
+ hres = jsdisp_propput_dontenum(ctx->global, MathW, jsval_obj(math));
+ jsdisp_release(math);
if(FAILED(hres))
return hres;
- V_VT(&var) = VT_DISPATCH;
- V_DISPATCH(&var) = (IDispatch*)_IDispatchEx_(math);
- hres = jsdisp_propput_name(ctx->global, MathW, &var, NULL/*FIXME*/, NULL/*FIXME*/);
- jsdisp_release(math);
+ hres = jsdisp_propput_dontenum(ctx->global, undefinedW, jsval_undefined());
+ if(FAILED(hres))
+ return hres;
+
+ hres = jsdisp_propput_dontenum(ctx->global, NaNW, jsval_number(NAN));
+ if(FAILED(hres))
+ return hres;
+ hres = jsdisp_propput_dontenum(ctx->global, InfinityW, jsval_number(INFINITY));
return hres;
}
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
+#include <assert.h>
+
#include "jscript.h"
#include "engine.h"
#include <objsafe.h>
#endif
typedef struct {
- const IActiveScriptVtbl *lpIActiveScriptVtbl;
- const IActiveScriptParseVtbl *lpIActiveScriptParseVtbl;
- const IActiveScriptParseProcedure2Vtbl *lpIActiveScriptParseProcedure2Vtbl;
- const IActiveScriptPropertyVtbl *lpIActiveScriptPropertyVtbl;
- const IObjectSafetyVtbl *lpIObjectSafetyVtbl;
+ IActiveScript IActiveScript_iface;
+ IActiveScriptParse IActiveScriptParse_iface;
+ IActiveScriptParseProcedure2 IActiveScriptParseProcedure2_iface;
+ IActiveScriptProperty IActiveScriptProperty_iface;
+ IObjectSafety IObjectSafety_iface;
+ IVariantChangeType IVariantChangeType_iface;
LONG ref;
LONG thread_id;
LCID lcid;
DWORD version;
+ BOOL is_encode;
IActiveScriptSite *site;
- parser_ctx_t *queue_head;
- parser_ctx_t *queue_tail;
+ bytecode_t *queue_head;
+ bytecode_t *queue_tail;
} JScript;
-#define ACTSCRIPT(x) ((IActiveScript*) &(x)->lpIActiveScriptVtbl)
-#define ASPARSE(x) (&(x)->lpIActiveScriptParseVtbl)
-#define ASPARSEPROC(x) (&(x)->lpIActiveScriptParseProcedure2Vtbl)
-#define ACTSCPPROP(x) (&(x)->lpIActiveScriptPropertyVtbl)
-#define OBJSAFETY(x) (&(x)->lpIObjectSafetyVtbl)
-
void script_release(script_ctx_t *ctx)
{
if(--ctx->ref)
return;
- jsheap_free(&ctx->tmp_heap);
- SysFreeString(ctx->last_match);
+ clear_ei(ctx);
+ if(ctx->cc)
+ release_cc(ctx->cc);
+ heap_pool_free(&ctx->tmp_heap);
+ if(ctx->last_match)
+ jsstr_release(ctx->last_match);
+
+ ctx->jscaller->ctx = NULL;
+ IServiceProvider_Release(&ctx->jscaller->IServiceProvider_iface);
+
heap_free(ctx);
}
return;
This->ctx->state = state;
- IActiveScriptSite_OnStateChange(This->site, state);
+ if(This->site)
+ IActiveScriptSite_OnStateChange(This->site, state);
}
static inline BOOL is_started(script_ctx_t *ctx)
|| ctx->state == SCRIPTSTATE_DISCONNECTED;
}
-static HRESULT exec_global_code(JScript *This, parser_ctx_t *parser_ctx)
+static HRESULT exec_global_code(JScript *This, bytecode_t *code)
{
exec_ctx_t *exec_ctx;
- jsexcept_t jsexcept;
HRESULT hres;
- hres = create_exec_ctx(This->ctx, NULL, This->ctx->global, NULL, &exec_ctx);
+ hres = create_exec_ctx(This->ctx, NULL, This->ctx->global, NULL, TRUE, &exec_ctx);
if(FAILED(hres))
return hres;
IActiveScriptSite_OnEnterScript(This->site);
- memset(&jsexcept, 0, sizeof(jsexcept));
- hres = exec_source(exec_ctx, parser_ctx, parser_ctx->source, EXECT_PROGRAM, &jsexcept, NULL);
- VariantClear(&jsexcept.var);
+ clear_ei(This->ctx);
+ hres = exec_source(exec_ctx, code, &code->global_code, FALSE, NULL);
exec_release(exec_ctx);
IActiveScriptSite_OnLeaveScript(This->site);
static void clear_script_queue(JScript *This)
{
- parser_ctx_t *iter, *iter2;
+ bytecode_t *iter, *iter2;
if(!This->queue_head)
return;
while(iter) {
iter2 = iter->next;
iter->next = NULL;
- parser_release(iter);
+ release_bytecode(iter);
iter = iter2;
}
static void exec_queued_code(JScript *This)
{
- parser_ctx_t *iter;
+ bytecode_t *iter;
for(iter = This->queue_head; iter; iter = iter->next)
exec_global_code(This, iter);
return S_OK;
}
+static void decrease_state(JScript *This, SCRIPTSTATE state)
+{
+ if(This->ctx) {
+ switch(This->ctx->state) {
+ case SCRIPTSTATE_CONNECTED:
+ change_state(This, SCRIPTSTATE_DISCONNECTED);
+ if(state == SCRIPTSTATE_DISCONNECTED)
+ return;
+ /* FALLTHROUGH */
+ case SCRIPTSTATE_STARTED:
+ case SCRIPTSTATE_DISCONNECTED:
+ clear_script_queue(This);
+
+ if(This->ctx->state == SCRIPTSTATE_DISCONNECTED)
+ change_state(This, SCRIPTSTATE_INITIALIZED);
+ if(state == SCRIPTSTATE_INITIALIZED)
+ return;
+ /* FALLTHROUGH */
+ case SCRIPTSTATE_INITIALIZED:
+ if(This->ctx->host_global) {
+ IDispatch_Release(This->ctx->host_global);
+ This->ctx->host_global = NULL;
+ }
+
+ if(This->ctx->named_items) {
+ named_item_t *iter, *iter2;
+
+ iter = This->ctx->named_items;
+ while(iter) {
+ iter2 = iter->next;
+
+ if(iter->disp)
+ IDispatch_Release(iter->disp);
+ heap_free(iter->name);
+ heap_free(iter);
+ iter = iter2;
+ }
+
+ This->ctx->named_items = NULL;
+ }
+
+ if(This->ctx->secmgr) {
+ IInternetHostSecurityManager_Release(This->ctx->secmgr);
+ This->ctx->secmgr = NULL;
+ }
+
+ if(This->ctx->site) {
+ IActiveScriptSite_Release(This->ctx->site);
+ This->ctx->site = NULL;
+ }
+
+ if(This->ctx->global) {
+ jsdisp_release(This->ctx->global);
+ This->ctx->global = NULL;
+ }
+ /* FALLTHROUGH */
+ case SCRIPTSTATE_UNINITIALIZED:
+ change_state(This, state);
+ break;
+ default:
+ assert(0);
+ }
+
+ change_state(This, state);
+ }else if(state == SCRIPTSTATE_UNINITIALIZED) {
+ if(This->site)
+ IActiveScriptSite_OnStateChange(This->site, state);
+ }else {
+ FIXME("NULL ctx\n");
+ }
+
+ if(state == SCRIPTSTATE_UNINITIALIZED)
+ This->thread_id = 0;
+
+ if(This->site) {
+ IActiveScriptSite_Release(This->site);
+ This->site = NULL;
+ }
+}
+
typedef struct {
- const IServiceProviderVtbl *lpIServiceProviderVtbl;
+ IServiceProvider IServiceProvider_iface;
LONG ref;
IServiceProvider *sp;
} AXSite;
-#define SERVPROV(x) ((IServiceProvider*) &(x)->lpIServiceProviderVtbl)
-
-#define SERVPROV_THIS(iface) DEFINE_THIS(AXSite, IServiceProvider, iface)
+static inline AXSite *impl_from_IServiceProvider(IServiceProvider *iface)
+{
+ return CONTAINING_RECORD(iface, AXSite, IServiceProvider_iface);
+}
static HRESULT WINAPI AXSite_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv)
{
- AXSite *This = SERVPROV_THIS(iface);
+ AXSite *This = impl_from_IServiceProvider(iface);
if(IsEqualGUID(&IID_IUnknown, riid)) {
TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
- *ppv = SERVPROV(This);
+ *ppv = &This->IServiceProvider_iface;
}else if(IsEqualGUID(&IID_IServiceProvider, riid)) {
TRACE("(%p)->(IID_IServiceProvider %p)\n", This, ppv);
- *ppv = SERVPROV(This);
+ *ppv = &This->IServiceProvider_iface;
}else {
TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
*ppv = NULL;
static ULONG WINAPI AXSite_AddRef(IServiceProvider *iface)
{
- AXSite *This = SERVPROV_THIS(iface);
+ AXSite *This = impl_from_IServiceProvider(iface);
LONG ref = InterlockedIncrement(&This->ref);
TRACE("(%p) ref=%d\n", This, ref);
static ULONG WINAPI AXSite_Release(IServiceProvider *iface)
{
- AXSite *This = SERVPROV_THIS(iface);
+ AXSite *This = impl_from_IServiceProvider(iface);
LONG ref = InterlockedDecrement(&This->ref);
TRACE("(%p) ref=%d\n", This, ref);
if(!ref)
+ {
+ if(This->sp)
+ IServiceProvider_Release(This->sp);
+
heap_free(This);
+ }
return ref;
}
static HRESULT WINAPI AXSite_QueryService(IServiceProvider *iface,
REFGUID guidService, REFIID riid, void **ppv)
{
- AXSite *This = SERVPROV_THIS(iface);
+ AXSite *This = impl_from_IServiceProvider(iface);
TRACE("(%p)->(%s %s %p)\n", This, debugstr_guid(guidService), debugstr_guid(riid), ppv);
+ if(!This->sp)
+ return E_NOINTERFACE;
+
return IServiceProvider_QueryService(This->sp, guidService, riid, ppv);
}
-#undef SERVPROV_THIS
-
static IServiceProviderVtbl AXSiteVtbl = {
AXSite_QueryInterface,
AXSite_AddRef,
IUnknown *create_ax_site(script_ctx_t *ctx)
{
- IServiceProvider *sp;
+ IServiceProvider *sp = NULL;
AXSite *ret;
HRESULT hres;
hres = IActiveScriptSite_QueryInterface(ctx->site, &IID_IServiceProvider, (void**)&sp);
if(FAILED(hres)) {
- ERR("Could not get IServiceProvider iface: %08x\n", hres);
- return NULL;
+ TRACE("Could not get IServiceProvider iface: %08x\n", hres);
}
ret = heap_alloc(sizeof(AXSite));
return NULL;
}
- ret->lpIServiceProviderVtbl = &AXSiteVtbl;
+ ret->IServiceProvider_iface.lpVtbl = &AXSiteVtbl;
ret->ref = 1;
ret->sp = sp;
- return (IUnknown*)SERVPROV(ret);
+ return (IUnknown*)&ret->IServiceProvider_iface;
}
-#define ACTSCRIPT_THIS(iface) DEFINE_THIS(JScript, IActiveScript, iface)
+static inline JScript *impl_from_IActiveScript(IActiveScript *iface)
+{
+ return CONTAINING_RECORD(iface, JScript, IActiveScript_iface);
+}
static HRESULT WINAPI JScript_QueryInterface(IActiveScript *iface, REFIID riid, void **ppv)
{
- JScript *This = ACTSCRIPT_THIS(iface);
+ JScript *This = impl_from_IActiveScript(iface);
*ppv = NULL;
if(IsEqualGUID(riid, &IID_IUnknown)) {
TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
- *ppv = ACTSCRIPT(This);
+ *ppv = &This->IActiveScript_iface;
}else if(IsEqualGUID(riid, &IID_IActiveScript)) {
TRACE("(%p)->(IID_IActiveScript %p)\n", This, ppv);
- *ppv = ACTSCRIPT(This);
+ *ppv = &This->IActiveScript_iface;
}else if(IsEqualGUID(riid, &IID_IActiveScriptParse)) {
TRACE("(%p)->(IID_IActiveScriptParse %p)\n", This, ppv);
- *ppv = ASPARSE(This);
+ *ppv = &This->IActiveScriptParse_iface;
}else if(IsEqualGUID(riid, &IID_IActiveScriptParseProcedure)) {
TRACE("(%p)->(IID_IActiveScriptParseProcedure %p)\n", This, ppv);
- *ppv = ASPARSEPROC(This);
+ *ppv = &This->IActiveScriptParseProcedure2_iface;
}else if(IsEqualGUID(riid, &IID_IActiveScriptParseProcedure2)) {
TRACE("(%p)->(IID_IActiveScriptParseProcedure2 %p)\n", This, ppv);
- *ppv = ASPARSEPROC(This);
+ *ppv = &This->IActiveScriptParseProcedure2_iface;
}else if(IsEqualGUID(riid, &IID_IActiveScriptProperty)) {
TRACE("(%p)->(IID_IActiveScriptProperty %p)\n", This, ppv);
- *ppv = ACTSCPPROP(This);
+ *ppv = &This->IActiveScriptProperty_iface;
}else if(IsEqualGUID(riid, &IID_IObjectSafety)) {
TRACE("(%p)->(IID_IObjectSafety %p)\n", This, ppv);
- *ppv = OBJSAFETY(This);
+ *ppv = &This->IObjectSafety_iface;
+ }else if(IsEqualGUID(riid, &IID_IVariantChangeType)) {
+ TRACE("(%p)->(IID_IVariantChangeType %p)\n", This, ppv);
+ *ppv = &This->IVariantChangeType_iface;
}
if(*ppv) {
static ULONG WINAPI JScript_AddRef(IActiveScript *iface)
{
- JScript *This = ACTSCRIPT_THIS(iface);
+ JScript *This = impl_from_IActiveScript(iface);
LONG ref = InterlockedIncrement(&This->ref);
TRACE("(%p) ref=%d\n", This, ref);
static ULONG WINAPI JScript_Release(IActiveScript *iface)
{
- JScript *This = ACTSCRIPT_THIS(iface);
+ JScript *This = impl_from_IActiveScript(iface);
LONG ref = InterlockedDecrement(&This->ref);
TRACE("(%p) ref=%d\n", iface, ref);
if(!ref) {
if(This->ctx && This->ctx->state != SCRIPTSTATE_CLOSED)
- IActiveScript_Close(ACTSCRIPT(This));
- if(This->ctx)
+ IActiveScript_Close(&This->IActiveScript_iface);
+ if(This->ctx) {
+ This->ctx->active_script = NULL;
script_release(This->ctx);
+ }
heap_free(This);
unlock_module();
}
static HRESULT WINAPI JScript_SetScriptSite(IActiveScript *iface,
IActiveScriptSite *pass)
{
- JScript *This = ACTSCRIPT_THIS(iface);
+ JScript *This = impl_from_IActiveScript(iface);
LCID lcid;
HRESULT hres;
static HRESULT WINAPI JScript_GetScriptSite(IActiveScript *iface, REFIID riid,
void **ppvObject)
{
- JScript *This = ACTSCRIPT_THIS(iface);
+ JScript *This = impl_from_IActiveScript(iface);
FIXME("(%p)->()\n", This);
return E_NOTIMPL;
}
static HRESULT WINAPI JScript_SetScriptState(IActiveScript *iface, SCRIPTSTATE ss)
{
- JScript *This = ACTSCRIPT_THIS(iface);
+ JScript *This = impl_from_IActiveScript(iface);
TRACE("(%p)->(%d)\n", This, ss);
- if(!This->ctx || GetCurrentThreadId() != This->thread_id)
+ if(This->thread_id && GetCurrentThreadId() != This->thread_id)
+ return E_UNEXPECTED;
+
+ if(ss == SCRIPTSTATE_UNINITIALIZED) {
+ if(This->ctx && This->ctx->state == SCRIPTSTATE_CLOSED)
+ return E_UNEXPECTED;
+
+ decrease_state(This, SCRIPTSTATE_UNINITIALIZED);
+ return S_OK;
+ }
+
+ if(!This->ctx)
return E_UNEXPECTED;
switch(ss) {
exec_queued_code(This);
break;
+ case SCRIPTSTATE_INITIALIZED:
+ FIXME("unimplemented SCRIPTSTATE_INITIALIZED\n");
+ return S_OK;
default:
FIXME("unimplemented state %d\n", ss);
return E_NOTIMPL;
static HRESULT WINAPI JScript_GetScriptState(IActiveScript *iface, SCRIPTSTATE *pssState)
{
- JScript *This = ACTSCRIPT_THIS(iface);
+ JScript *This = impl_from_IActiveScript(iface);
TRACE("(%p)->(%p)\n", This, pssState);
if(!pssState)
return E_POINTER;
- if(!This->thread_id) {
- *pssState = SCRIPTSTATE_UNINITIALIZED;
- return S_OK;
- }
-
- if(This->thread_id != GetCurrentThreadId())
+ if(This->thread_id && This->thread_id != GetCurrentThreadId())
return E_UNEXPECTED;
*pssState = This->ctx ? This->ctx->state : SCRIPTSTATE_UNINITIALIZED;
static HRESULT WINAPI JScript_Close(IActiveScript *iface)
{
- JScript *This = ACTSCRIPT_THIS(iface);
+ JScript *This = impl_from_IActiveScript(iface);
TRACE("(%p)->()\n", This);
- if(This->thread_id != GetCurrentThreadId())
+ if(This->thread_id && This->thread_id != GetCurrentThreadId())
return E_UNEXPECTED;
- if(This->ctx) {
- if(This->ctx->state == SCRIPTSTATE_CONNECTED)
- change_state(This, SCRIPTSTATE_DISCONNECTED);
-
- clear_script_queue(This);
-
- if(This->ctx->state == SCRIPTSTATE_DISCONNECTED)
- change_state(This, SCRIPTSTATE_INITIALIZED);
-
- if(This->ctx->host_global) {
- IDispatch_Release(This->ctx->host_global);
- This->ctx->host_global = NULL;
- }
-
- if(This->ctx->named_items) {
- named_item_t *iter, *iter2;
-
- iter = This->ctx->named_items;
- while(iter) {
- iter2 = iter->next;
-
- if(iter->disp)
- IDispatch_Release(iter->disp);
- heap_free(iter->name);
- heap_free(iter);
- iter = iter2;
- }
-
- This->ctx->named_items = NULL;
- }
-
- if(This->ctx->secmgr) {
- IInternetHostSecurityManager_Release(This->ctx->secmgr);
- This->ctx->secmgr = NULL;
- }
-
- if(This->ctx->site) {
- IActiveScriptSite_Release(This->ctx->site);
- This->ctx->site = NULL;
- }
-
- if (This->site)
- change_state(This, SCRIPTSTATE_CLOSED);
-
- if(This->ctx->global) {
- jsdisp_release(This->ctx->global);
- This->ctx->global = NULL;
- }
- }
-
- if(This->site) {
- IActiveScriptSite_Release(This->site);
- This->site = NULL;
- }
-
+ decrease_state(This, SCRIPTSTATE_CLOSED);
return S_OK;
}
static HRESULT WINAPI JScript_AddNamedItem(IActiveScript *iface,
LPCOLESTR pstrName, DWORD dwFlags)
{
- JScript *This = ACTSCRIPT_THIS(iface);
+ JScript *This = impl_from_IActiveScript(iface);
named_item_t *item;
IDispatch *disp = NULL;
HRESULT hres;
item->flags = dwFlags;
item->name = heap_strdupW(pstrName);
if(!item->name) {
- IDispatch_Release(disp);
+ if(disp)
+ IDispatch_Release(disp);
heap_free(item);
return E_OUTOFMEMORY;
}
static HRESULT WINAPI JScript_AddTypeLib(IActiveScript *iface, REFGUID rguidTypeLib,
DWORD dwMajor, DWORD dwMinor, DWORD dwFlags)
{
- JScript *This = ACTSCRIPT_THIS(iface);
+ JScript *This = impl_from_IActiveScript(iface);
FIXME("(%p)->()\n", This);
return E_NOTIMPL;
}
static HRESULT WINAPI JScript_GetScriptDispatch(IActiveScript *iface, LPCOLESTR pstrItemName,
IDispatch **ppdisp)
{
- JScript *This = ACTSCRIPT_THIS(iface);
+ JScript *This = impl_from_IActiveScript(iface);
TRACE("(%p)->(%p)\n", This, ppdisp);
return E_UNEXPECTED;
}
- *ppdisp = (IDispatch*)_IDispatchEx_(This->ctx->global);
+ *ppdisp = to_disp(This->ctx->global);
IDispatch_AddRef(*ppdisp);
return S_OK;
}
static HRESULT WINAPI JScript_GetCurrentScriptThreadID(IActiveScript *iface,
SCRIPTTHREADID *pstridThread)
{
- JScript *This = ACTSCRIPT_THIS(iface);
+ JScript *This = impl_from_IActiveScript(iface);
FIXME("(%p)->()\n", This);
return E_NOTIMPL;
}
static HRESULT WINAPI JScript_GetScriptThreadID(IActiveScript *iface,
DWORD dwWin32ThreadId, SCRIPTTHREADID *pstidThread)
{
- JScript *This = ACTSCRIPT_THIS(iface);
+ JScript *This = impl_from_IActiveScript(iface);
FIXME("(%p)->()\n", This);
return E_NOTIMPL;
}
static HRESULT WINAPI JScript_GetScriptThreadState(IActiveScript *iface,
SCRIPTTHREADID stidThread, SCRIPTTHREADSTATE *pstsState)
{
- JScript *This = ACTSCRIPT_THIS(iface);
+ JScript *This = impl_from_IActiveScript(iface);
FIXME("(%p)->()\n", This);
return E_NOTIMPL;
}
static HRESULT WINAPI JScript_InterruptScriptThread(IActiveScript *iface,
SCRIPTTHREADID stidThread, const EXCEPINFO *pexcepinfo, DWORD dwFlags)
{
- JScript *This = ACTSCRIPT_THIS(iface);
+ JScript *This = impl_from_IActiveScript(iface);
FIXME("(%p)->()\n", This);
return E_NOTIMPL;
}
static HRESULT WINAPI JScript_Clone(IActiveScript *iface, IActiveScript **ppscript)
{
- JScript *This = ACTSCRIPT_THIS(iface);
+ JScript *This = impl_from_IActiveScript(iface);
FIXME("(%p)->()\n", This);
return E_NOTIMPL;
}
-#undef ACTSCRIPT_THIS
-
static const IActiveScriptVtbl JScriptVtbl = {
JScript_QueryInterface,
JScript_AddRef,
JScript_Clone
};
-#define ASPARSE_THIS(iface) DEFINE_THIS(JScript, IActiveScriptParse, iface)
+static inline JScript *impl_from_IActiveScriptParse(IActiveScriptParse *iface)
+{
+ return CONTAINING_RECORD(iface, JScript, IActiveScriptParse_iface);
+}
static HRESULT WINAPI JScriptParse_QueryInterface(IActiveScriptParse *iface, REFIID riid, void **ppv)
{
- JScript *This = ASPARSE_THIS(iface);
- return IActiveScript_QueryInterface(ACTSCRIPT(This), riid, ppv);
+ JScript *This = impl_from_IActiveScriptParse(iface);
+ return IActiveScript_QueryInterface(&This->IActiveScript_iface, riid, ppv);
}
static ULONG WINAPI JScriptParse_AddRef(IActiveScriptParse *iface)
{
- JScript *This = ASPARSE_THIS(iface);
- return IActiveScript_AddRef(ACTSCRIPT(This));
+ JScript *This = impl_from_IActiveScriptParse(iface);
+ return IActiveScript_AddRef(&This->IActiveScript_iface);
}
static ULONG WINAPI JScriptParse_Release(IActiveScriptParse *iface)
{
- JScript *This = ASPARSE_THIS(iface);
- return IActiveScript_Release(ACTSCRIPT(This));
+ JScript *This = impl_from_IActiveScriptParse(iface);
+ return IActiveScript_Release(&This->IActiveScript_iface);
}
static HRESULT WINAPI JScriptParse_InitNew(IActiveScriptParse *iface)
{
- JScript *This = ASPARSE_THIS(iface);
+ JScript *This = impl_from_IActiveScriptParse(iface);
script_ctx_t *ctx;
+ HRESULT hres;
TRACE("(%p)\n", This);
ctx->ref = 1;
ctx->state = SCRIPTSTATE_UNINITIALIZED;
+ ctx->active_script = &This->IActiveScript_iface;
ctx->safeopt = This->safeopt;
ctx->version = This->version;
- jsheap_init(&ctx->tmp_heap);
+ ctx->ei.val = jsval_undefined();
+ heap_pool_init(&ctx->tmp_heap);
+
+ hres = create_jscaller(ctx);
+ if(FAILED(hres)) {
+ heap_free(ctx);
+ return hres;
+ }
+
+ ctx->last_match = jsstr_empty();
ctx = InterlockedCompareExchangePointer((void**)&This->ctx, ctx, NULL);
if(ctx) {
CTXARG_T dwSourceContextCookie, ULONG ulStartingLineNumber, DWORD dwFlags,
BSTR *pbstrName, EXCEPINFO *pexcepinfo)
{
- JScript *This = ASPARSE_THIS(iface);
+ JScript *This = impl_from_IActiveScriptParse(iface);
FIXME("(%p)->(%s %s %s %s %s %s %s %u %x %p %p)\n", This, debugstr_w(pstrDefaultName),
debugstr_w(pstrCode), debugstr_w(pstrItemName), debugstr_w(pstrSubItemName),
debugstr_w(pstrEventName), debugstr_w(pstrDelimiter), wine_dbgstr_longlong(dwSourceContextCookie),
LPCOLESTR pstrDelimiter, CTXARG_T dwSourceContextCookie, ULONG ulStartingLine,
DWORD dwFlags, VARIANT *pvarResult, EXCEPINFO *pexcepinfo)
{
- JScript *This = ASPARSE_THIS(iface);
- parser_ctx_t *parser_ctx;
+ JScript *This = impl_from_IActiveScriptParse(iface);
+ bytecode_t *code;
HRESULT hres;
TRACE("(%p)->(%s %s %p %s %s %u %x %p %p)\n", This, debugstr_w(pstrCode),
if(This->thread_id != GetCurrentThreadId() || This->ctx->state == SCRIPTSTATE_CLOSED)
return E_UNEXPECTED;
- hres = script_parse(This->ctx, pstrCode, pstrDelimiter, &parser_ctx);
+ hres = compile_script(This->ctx, pstrCode, NULL, pstrDelimiter, (dwFlags & SCRIPTTEXT_ISEXPRESSION) != 0,
+ This->is_encode, &code);
if(FAILED(hres))
return hres;
+ if(dwFlags & SCRIPTTEXT_ISEXPRESSION) {
+ exec_ctx_t *exec_ctx;
+
+ hres = create_exec_ctx(This->ctx, NULL, This->ctx->global, NULL, TRUE, &exec_ctx);
+ if(SUCCEEDED(hres)) {
+ jsval_t r;
+
+ IActiveScriptSite_OnEnterScript(This->site);
+
+ clear_ei(This->ctx);
+ hres = exec_source(exec_ctx, code, &code->global_code, TRUE, &r);
+ if(SUCCEEDED(hres)) {
+ hres = jsval_to_variant(r, pvarResult);
+ jsval_release(r);
+ }
+ exec_release(exec_ctx);
+
+ IActiveScriptSite_OnLeaveScript(This->site);
+ }
+
+ return hres;
+ }
+
if(!is_started(This->ctx)) {
if(This->queue_tail)
- This->queue_tail = This->queue_tail->next = parser_ctx;
+ This->queue_tail = This->queue_tail->next = code;
else
- This->queue_head = This->queue_tail = parser_ctx;
+ This->queue_head = This->queue_tail = code;
return S_OK;
}
- hres = exec_global_code(This, parser_ctx);
- parser_release(parser_ctx);
+ hres = exec_global_code(This, code);
+ release_bytecode(code);
return hres;
}
-#undef ASPARSE_THIS
-
static const IActiveScriptParseVtbl JScriptParseVtbl = {
JScriptParse_QueryInterface,
JScriptParse_AddRef,
JScriptParse_ParseScriptText
};
-#define ASPARSEPROC_THIS(iface) DEFINE_THIS(JScript, IActiveScriptParseProcedure2, iface)
+static inline JScript *impl_from_IActiveScriptParseProcedure2(IActiveScriptParseProcedure2 *iface)
+{
+ return CONTAINING_RECORD(iface, JScript, IActiveScriptParseProcedure2_iface);
+}
static HRESULT WINAPI JScriptParseProcedure_QueryInterface(IActiveScriptParseProcedure2 *iface, REFIID riid, void **ppv)
{
- JScript *This = ASPARSEPROC_THIS(iface);
- return IActiveScript_QueryInterface(ACTSCRIPT(This), riid, ppv);
+ JScript *This = impl_from_IActiveScriptParseProcedure2(iface);
+ return IActiveScript_QueryInterface(&This->IActiveScript_iface, riid, ppv);
}
static ULONG WINAPI JScriptParseProcedure_AddRef(IActiveScriptParseProcedure2 *iface)
{
- JScript *This = ASPARSEPROC_THIS(iface);
- return IActiveScript_AddRef(ACTSCRIPT(This));
+ JScript *This = impl_from_IActiveScriptParseProcedure2(iface);
+ return IActiveScript_AddRef(&This->IActiveScript_iface);
}
static ULONG WINAPI JScriptParseProcedure_Release(IActiveScriptParseProcedure2 *iface)
{
- JScript *This = ASPARSEPROC_THIS(iface);
- return IActiveScript_Release(ACTSCRIPT(This));
+ JScript *This = impl_from_IActiveScriptParseProcedure2(iface);
+ return IActiveScript_Release(&This->IActiveScript_iface);
}
static HRESULT WINAPI JScriptParseProcedure_ParseProcedureText(IActiveScriptParseProcedure2 *iface,
LPCOLESTR pstrItemName, IUnknown *punkContext, LPCOLESTR pstrDelimiter,
CTXARG_T dwSourceContextCookie, ULONG ulStartingLineNumber, DWORD dwFlags, IDispatch **ppdisp)
{
- JScript *This = ASPARSEPROC_THIS(iface);
- parser_ctx_t *parser_ctx;
- DispatchEx *dispex;
+ JScript *This = impl_from_IActiveScriptParseProcedure2(iface);
+ bytecode_t *code;
+ jsdisp_t *dispex;
HRESULT hres;
TRACE("(%p)->(%s %s %s %s %p %s %s %u %x %p)\n", This, debugstr_w(pstrCode), debugstr_w(pstrFormalParams),
if(This->thread_id != GetCurrentThreadId() || This->ctx->state == SCRIPTSTATE_CLOSED)
return E_UNEXPECTED;
- hres = script_parse(This->ctx, pstrCode, pstrDelimiter, &parser_ctx);
+ hres = compile_script(This->ctx, pstrCode, pstrFormalParams, pstrDelimiter, FALSE, This->is_encode, &code);
if(FAILED(hres)) {
WARN("Parse failed %08x\n", hres);
return hres;
}
- hres = create_source_function(parser_ctx, NULL, parser_ctx->source, NULL, NULL, 0, &dispex);
- parser_release(parser_ctx);
+ hres = create_source_function(This->ctx, code, &code->global_code, NULL, &dispex);
+ release_bytecode(code);
if(FAILED(hres))
return hres;
- *ppdisp = (IDispatch*)_IDispatchEx_(dispex);
+ *ppdisp = to_disp(dispex);
return S_OK;
}
-#undef ASPARSEPROC_THIS
-
static const IActiveScriptParseProcedure2Vtbl JScriptParseProcedureVtbl = {
JScriptParseProcedure_QueryInterface,
JScriptParseProcedure_AddRef,
JScriptParseProcedure_ParseProcedureText,
};
-#define ACTSCPPROP_THIS(iface) DEFINE_THIS(JScript, IActiveScriptProperty, iface)
+static inline JScript *impl_from_IActiveScriptProperty(IActiveScriptProperty *iface)
+{
+ return CONTAINING_RECORD(iface, JScript, IActiveScriptProperty_iface);
+}
static HRESULT WINAPI JScriptProperty_QueryInterface(IActiveScriptProperty *iface, REFIID riid, void **ppv)
{
- JScript *This = ACTSCPPROP_THIS(iface);
- return IActiveScript_QueryInterface(ACTSCRIPT(This), riid, ppv);
+ JScript *This = impl_from_IActiveScriptProperty(iface);
+ return IActiveScript_QueryInterface(&This->IActiveScript_iface, riid, ppv);
}
static ULONG WINAPI JScriptProperty_AddRef(IActiveScriptProperty *iface)
{
- JScript *This = ACTSCPPROP_THIS(iface);
- return IActiveScript_AddRef(ACTSCRIPT(This));
+ JScript *This = impl_from_IActiveScriptProperty(iface);
+ return IActiveScript_AddRef(&This->IActiveScript_iface);
}
static ULONG WINAPI JScriptProperty_Release(IActiveScriptProperty *iface)
{
- JScript *This = ACTSCPPROP_THIS(iface);
- return IActiveScript_Release(ACTSCRIPT(This));
+ JScript *This = impl_from_IActiveScriptProperty(iface);
+ return IActiveScript_Release(&This->IActiveScript_iface);
}
static HRESULT WINAPI JScriptProperty_GetProperty(IActiveScriptProperty *iface, DWORD dwProperty,
VARIANT *pvarIndex, VARIANT *pvarValue)
{
- JScript *This = ACTSCPPROP_THIS(iface);
+ JScript *This = impl_from_IActiveScriptProperty(iface);
FIXME("(%p)->(%x %p %p)\n", This, dwProperty, pvarIndex, pvarValue);
return E_NOTIMPL;
}
static HRESULT WINAPI JScriptProperty_SetProperty(IActiveScriptProperty *iface, DWORD dwProperty,
VARIANT *pvarIndex, VARIANT *pvarValue)
{
- JScript *This = ACTSCPPROP_THIS(iface);
+ JScript *This = impl_from_IActiveScriptProperty(iface);
TRACE("(%p)->(%x %s %s)\n", This, dwProperty, debugstr_variant(pvarIndex), debugstr_variant(pvarValue));
return S_OK;
}
-#undef ACTSCPPROP_THIS
-
static const IActiveScriptPropertyVtbl JScriptPropertyVtbl = {
JScriptProperty_QueryInterface,
JScriptProperty_AddRef,
JScriptProperty_SetProperty
};
-#define OBJSAFETY_THIS(iface) DEFINE_THIS(JScript, IObjectSafety, iface)
+static inline JScript *impl_from_IObjectSafety(IObjectSafety *iface)
+{
+ return CONTAINING_RECORD(iface, JScript, IObjectSafety_iface);
+}
static HRESULT WINAPI JScriptSafety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv)
{
- JScript *This = OBJSAFETY_THIS(iface);
- return IActiveScript_QueryInterface(ACTSCRIPT(This), riid, ppv);
+ JScript *This = impl_from_IObjectSafety(iface);
+ return IActiveScript_QueryInterface(&This->IActiveScript_iface, riid, ppv);
}
static ULONG WINAPI JScriptSafety_AddRef(IObjectSafety *iface)
{
- JScript *This = OBJSAFETY_THIS(iface);
- return IActiveScript_AddRef(ACTSCRIPT(This));
+ JScript *This = impl_from_IObjectSafety(iface);
+ return IActiveScript_AddRef(&This->IActiveScript_iface);
}
static ULONG WINAPI JScriptSafety_Release(IObjectSafety *iface)
{
- JScript *This = OBJSAFETY_THIS(iface);
- return IActiveScript_Release(ACTSCRIPT(This));
+ JScript *This = impl_from_IObjectSafety(iface);
+ return IActiveScript_Release(&This->IActiveScript_iface);
}
#define SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_DISPEX|INTERFACE_USES_SECURITY_MANAGER)
static HRESULT WINAPI JScriptSafety_GetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
DWORD *pdwSupportedOptions, DWORD *pdwEnabledOptions)
{
- JScript *This = OBJSAFETY_THIS(iface);
+ JScript *This = impl_from_IObjectSafety(iface);
TRACE("(%p)->(%s %p %p)\n", This, debugstr_guid(riid), pdwSupportedOptions, pdwEnabledOptions);
static HRESULT WINAPI JScriptSafety_SetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
DWORD dwOptionSetMask, DWORD dwEnabledOptions)
{
- JScript *This = OBJSAFETY_THIS(iface);
+ JScript *This = impl_from_IObjectSafety(iface);
TRACE("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), dwOptionSetMask, dwEnabledOptions);
if(dwOptionSetMask & ~SUPPORTED_OPTIONS)
return E_FAIL;
- This->safeopt = dwEnabledOptions & dwEnabledOptions;
+ This->safeopt = (dwEnabledOptions & dwOptionSetMask) | (This->safeopt & ~dwOptionSetMask) | INTERFACE_USES_DISPEX;
return S_OK;
}
-#undef OBJSAFETY_THIS
-
static const IObjectSafetyVtbl JScriptSafetyVtbl = {
JScriptSafety_QueryInterface,
JScriptSafety_AddRef,
JScriptSafety_SetInterfaceSafetyOptions
};
-HRESULT WINAPI JScriptFactory_CreateInstance(IClassFactory *iface, IUnknown *pUnkOuter,
- REFIID riid, void **ppv)
+static inline JScript *impl_from_IVariantChangeType(IVariantChangeType *iface)
{
- JScript *ret;
+ return CONTAINING_RECORD(iface, JScript, IVariantChangeType_iface);
+}
+
+static HRESULT WINAPI VariantChangeType_QueryInterface(IVariantChangeType *iface, REFIID riid, void **ppv)
+{
+ JScript *This = impl_from_IVariantChangeType(iface);
+ return IActiveScript_QueryInterface(&This->IActiveScript_iface, riid, ppv);
+}
+
+static ULONG WINAPI VariantChangeType_AddRef(IVariantChangeType *iface)
+{
+ JScript *This = impl_from_IVariantChangeType(iface);
+ return IActiveScript_AddRef(&This->IActiveScript_iface);
+}
+
+static ULONG WINAPI VariantChangeType_Release(IVariantChangeType *iface)
+{
+ JScript *This = impl_from_IVariantChangeType(iface);
+ return IActiveScript_Release(&This->IActiveScript_iface);
+}
+
+static HRESULT WINAPI VariantChangeType_ChangeType(IVariantChangeType *iface, VARIANT *dst, VARIANT *src, LCID lcid, VARTYPE vt)
+{
+ JScript *This = impl_from_IVariantChangeType(iface);
+ VARIANT res;
HRESULT hres;
- TRACE("(%p %s %p)\n", pUnkOuter, debugstr_guid(riid), ppv);
+ TRACE("(%p)->(%p %p%s %x %d)\n", This, dst, src, debugstr_variant(src), lcid, vt);
- lock_module();
+ if(!This->ctx) {
+ FIXME("Object uninitialized\n");
+ return E_UNEXPECTED;
+ }
+
+ hres = variant_change_type(This->ctx, &res, src, vt);
+ if(FAILED(hres))
+ return hres;
+
+ hres = VariantClear(dst);
+ if(FAILED(hres)) {
+ VariantClear(&res);
+ return hres;
+ }
+
+ *dst = res;
+ return S_OK;
+}
+
+static const IVariantChangeTypeVtbl VariantChangeTypeVtbl = {
+ VariantChangeType_QueryInterface,
+ VariantChangeType_AddRef,
+ VariantChangeType_Release,
+ VariantChangeType_ChangeType
+};
+
+HRESULT create_jscript_object(BOOL is_encode, REFIID riid, void **ppv)
+{
+ JScript *ret;
+ HRESULT hres;
ret = heap_alloc_zero(sizeof(*ret));
if(!ret)
return E_OUTOFMEMORY;
- ret->lpIActiveScriptVtbl = &JScriptVtbl;
- ret->lpIActiveScriptParseVtbl = &JScriptParseVtbl;
- ret->lpIActiveScriptParseProcedure2Vtbl = &JScriptParseProcedureVtbl;
- ret->lpIActiveScriptPropertyVtbl = &JScriptPropertyVtbl;
- ret->lpIObjectSafetyVtbl = &JScriptSafetyVtbl;
+ lock_module();
+
+ ret->IActiveScript_iface.lpVtbl = &JScriptVtbl;
+ ret->IActiveScriptParse_iface.lpVtbl = &JScriptParseVtbl;
+ ret->IActiveScriptParseProcedure2_iface.lpVtbl = &JScriptParseProcedureVtbl;
+ ret->IActiveScriptProperty_iface.lpVtbl = &JScriptPropertyVtbl;
+ ret->IObjectSafety_iface.lpVtbl = &JScriptSafetyVtbl;
+ ret->IVariantChangeType_iface.lpVtbl = &VariantChangeTypeVtbl;
ret->ref = 1;
ret->safeopt = INTERFACE_USES_DISPEX;
+ ret->is_encode = is_encode;
- hres = IActiveScript_QueryInterface(ACTSCRIPT(ret), riid, ppv);
- IActiveScript_Release(ACTSCRIPT(ret));
+ hres = IActiveScript_QueryInterface(&ret->IActiveScript_iface, riid, ppv);
+ IActiveScript_Release(&ret->IActiveScript_iface);
return hres;
}
#include <wine/unicode.h>
#include <wine/list.h>
-#define JSCRIPT_ERROR 0x800A0000
-
+typedef struct _jsval_t jsval_t;
+typedef struct _jsstr_t jsstr_t;
typedef struct _script_ctx_t script_ctx_t;
typedef struct _exec_ctx_t exec_ctx_t;
typedef struct _dispex_prop_t dispex_prop_t;
-typedef struct {
- EXCEPINFO ei;
- VARIANT var;
-} jsexcept_t;
-
typedef struct {
void **blocks;
DWORD block_cnt;
DWORD offset;
BOOL mark;
struct list custom_blocks;
-} jsheap_t;
+} heap_pool_t;
+
+void heap_pool_init(heap_pool_t*) DECLSPEC_HIDDEN;
+void *heap_pool_alloc(heap_pool_t*,DWORD) __WINE_ALLOC_SIZE(2) DECLSPEC_HIDDEN;
+void *heap_pool_grow(heap_pool_t*,void*,DWORD,DWORD) DECLSPEC_HIDDEN;
+void heap_pool_clear(heap_pool_t*) DECLSPEC_HIDDEN;
+void heap_pool_free(heap_pool_t*) DECLSPEC_HIDDEN;
+heap_pool_t *heap_pool_mark(heap_pool_t*) DECLSPEC_HIDDEN;
+
+static inline void *heap_alloc(size_t len)
+{
+ return HeapAlloc(GetProcessHeap(), 0, len);
+}
+
+static inline void *heap_alloc_zero(size_t len)
+{
+ return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
+}
+
+static inline void *heap_realloc(void *mem, size_t len)
+{
+ return HeapReAlloc(GetProcessHeap(), 0, mem, len);
+}
+
+static inline BOOL heap_free(void *mem)
+{
+ return HeapFree(GetProcessHeap(), 0, mem);
+}
+
+static inline LPWSTR heap_strdupW(LPCWSTR str)
+{
+ LPWSTR ret = NULL;
+
+ if(str) {
+ DWORD size;
+
+ size = (strlenW(str)+1)*sizeof(WCHAR);
+ ret = heap_alloc(size);
+ if(ret)
+ memcpy(ret, str, size);
+ }
-void jsheap_init(jsheap_t*);
-void *jsheap_alloc(jsheap_t*,DWORD);
-void *jsheap_grow(jsheap_t*,void*,DWORD,DWORD);
-void jsheap_clear(jsheap_t*);
-void jsheap_free(jsheap_t*);
-jsheap_t *jsheap_mark(jsheap_t*);
+ return ret;
+}
-typedef struct DispatchEx DispatchEx;
+typedef struct jsdisp_t jsdisp_t;
-extern HINSTANCE jscript_hinstance;
+extern HINSTANCE jscript_hinstance DECLSPEC_HIDDEN;
-#define PROPF_ARGMASK 0x00ff
-#define PROPF_METHOD 0x0100
-#define PROPF_ENUM 0x0200
-#define PROPF_CONSTR 0x0400
-#define PROPF_CONST 0x0800
+#define PROPF_ARGMASK 0x00ff
+#define PROPF_METHOD 0x0100
+#define PROPF_ENUM 0x0200
+#define PROPF_CONSTR 0x0400
+#define PROPF_CONST 0x0800
+#define PROPF_DONTDELETE 0x1000
/* NOTE: Keep in sync with names in Object.toString implementation */
typedef enum {
JSCLASS_OBJECT,
JSCLASS_REGEXP,
JSCLASS_STRING,
- JSCLASS_ARGUMENTS
+ JSCLASS_ARGUMENTS,
+ JSCLASS_VBARRAY
} jsclass_t;
-DispatchEx *iface_to_jsdisp(IUnknown*);
+jsdisp_t *iface_to_jsdisp(IUnknown*) DECLSPEC_HIDDEN;
typedef struct {
union {
IDispatch *disp;
IDispatchEx *dispex;
- DispatchEx *jsdisp;
+ jsdisp_t *jsdisp;
} u;
DWORD flags;
} vdisp_t;
return (vdisp->flags & VDISP_DISPEX) != 0;
}
-static inline void set_jsdisp(vdisp_t *vdisp, DispatchEx *jsdisp)
+static inline void set_jsdisp(vdisp_t *vdisp, jsdisp_t *jsdisp)
{
vdisp->u.jsdisp = jsdisp;
vdisp->flags = VDISP_JSDISP | VDISP_DISPEX;
static inline void set_disp(vdisp_t *vdisp, IDispatch *disp)
{
IDispatchEx *dispex;
- DispatchEx *jsdisp;
+ jsdisp_t *jsdisp;
HRESULT hres;
jsdisp = iface_to_jsdisp((IUnknown*)disp);
vdisp->flags = 0;
}
-static inline DispatchEx *get_jsdisp(vdisp_t *vdisp)
+static inline jsdisp_t *get_jsdisp(vdisp_t *vdisp)
{
return is_jsdisp(vdisp) ? vdisp->u.jsdisp : NULL;
}
-typedef HRESULT (*builtin_invoke_t)(script_ctx_t*,vdisp_t*,WORD,DISPPARAMS*,VARIANT*,jsexcept_t*,IServiceProvider*);
+typedef HRESULT (*builtin_invoke_t)(script_ctx_t*,vdisp_t*,WORD,unsigned,jsval_t*,jsval_t*);
typedef struct {
const WCHAR *name;
builtin_prop_t value_prop;
DWORD props_cnt;
const builtin_prop_t *props;
- void (*destructor)(DispatchEx*);
- void (*on_put)(DispatchEx*,const WCHAR*);
+ void (*destructor)(jsdisp_t*);
+ void (*on_put)(jsdisp_t*,const WCHAR*);
+ unsigned (*idx_length)(jsdisp_t*);
+ HRESULT (*idx_get)(jsdisp_t*,unsigned,jsval_t*);
+ HRESULT (*idx_put)(jsdisp_t*,unsigned,jsval_t);
} builtin_info_t;
-struct DispatchEx {
- const IDispatchExVtbl *lpIDispatchExVtbl;
+struct jsdisp_t {
+ IDispatchEx IDispatchEx_iface;
LONG ref;
dispex_prop_t *props;
script_ctx_t *ctx;
- DispatchEx *prototype;
+ jsdisp_t *prototype;
const builtin_info_t *builtin_info;
};
-#define _IDispatchEx_(x) ((IDispatchEx*) &(x)->lpIDispatchExVtbl)
+static inline IDispatch *to_disp(jsdisp_t *jsdisp)
+{
+ return (IDispatch*)&jsdisp->IDispatchEx_iface;
+}
+
+jsdisp_t *as_jsdisp(IDispatch*) DECLSPEC_HIDDEN;
+jsdisp_t *to_jsdisp(IDispatch*) DECLSPEC_HIDDEN;
+void jsdisp_free(jsdisp_t*) DECLSPEC_HIDDEN;
+
+#ifndef TRACE_REFCNT
+
+/*
+ * We do a lot of refcount calls during script execution, so having an inline
+ * version is a nice perf win. Define TRACE_REFCNT macro when debugging
+ * refcount bugs to have traces. Also, since jsdisp_t is not thread safe anyways,
+ * there is no point in using atomic operations.
+ */
+static inline jsdisp_t *jsdisp_addref(jsdisp_t *jsdisp)
+{
+ jsdisp->ref++;
+ return jsdisp;
+}
-static inline void jsdisp_release(DispatchEx *jsdisp)
+static inline void jsdisp_release(jsdisp_t *jsdisp)
{
- IDispatchEx_Release(_IDispatchEx_(jsdisp));
+ if(!--jsdisp->ref)
+ jsdisp_free(jsdisp);
}
-HRESULT create_dispex(script_ctx_t*,const builtin_info_t*,DispatchEx*,DispatchEx**);
-HRESULT init_dispex(DispatchEx*,script_ctx_t*,const builtin_info_t*,DispatchEx*);
-HRESULT init_dispex_from_constr(DispatchEx*,script_ctx_t*,const builtin_info_t*,DispatchEx*);
-
-HRESULT disp_call(script_ctx_t*,IDispatch*,DISPID,WORD,DISPPARAMS*,VARIANT*,jsexcept_t*,IServiceProvider*);
-HRESULT jsdisp_call_value(DispatchEx*,WORD,DISPPARAMS*,VARIANT*,jsexcept_t*,IServiceProvider*);
-HRESULT jsdisp_call(DispatchEx*,DISPID,WORD,DISPPARAMS*,VARIANT*,jsexcept_t*,IServiceProvider*);
-HRESULT jsdisp_call_name(DispatchEx*,const WCHAR*,WORD,DISPPARAMS*,VARIANT*,jsexcept_t*,IServiceProvider*);
-HRESULT disp_propget(script_ctx_t*,IDispatch*,DISPID,VARIANT*,jsexcept_t*,IServiceProvider*);
-HRESULT disp_propput(script_ctx_t*,IDispatch*,DISPID,VARIANT*,jsexcept_t*,IServiceProvider*);
-HRESULT jsdisp_propget(DispatchEx*,DISPID,VARIANT*,jsexcept_t*,IServiceProvider*);
-HRESULT jsdisp_propput_name(DispatchEx*,const WCHAR*,VARIANT*,jsexcept_t*,IServiceProvider*);
-HRESULT jsdisp_propput_const(DispatchEx*,const WCHAR*,VARIANT*);
-HRESULT jsdisp_propput_idx(DispatchEx*,DWORD,VARIANT*,jsexcept_t*,IServiceProvider*);
-HRESULT jsdisp_propget_name(DispatchEx*,LPCWSTR,VARIANT*,jsexcept_t*,IServiceProvider*);
-HRESULT jsdisp_get_idx(DispatchEx*,DWORD,VARIANT*,jsexcept_t*,IServiceProvider*);
-HRESULT jsdisp_get_id(DispatchEx*,const WCHAR*,DWORD,DISPID*);
-HRESULT jsdisp_delete_idx(DispatchEx*,DWORD);
+#else
+
+jsdisp_t *jsdisp_addref(jsdisp_t*) DECLSPEC_HIDDEN;
+void jsdisp_release(jsdisp_t*) DECLSPEC_HIDDEN;
+
+#endif
+
+HRESULT create_dispex(script_ctx_t*,const builtin_info_t*,jsdisp_t*,jsdisp_t**) DECLSPEC_HIDDEN;
+HRESULT init_dispex(jsdisp_t*,script_ctx_t*,const builtin_info_t*,jsdisp_t*) DECLSPEC_HIDDEN;
+HRESULT init_dispex_from_constr(jsdisp_t*,script_ctx_t*,const builtin_info_t*,jsdisp_t*) DECLSPEC_HIDDEN;
+
+HRESULT disp_call(script_ctx_t*,IDispatch*,DISPID,WORD,unsigned,jsval_t*,jsval_t*) DECLSPEC_HIDDEN;
+HRESULT disp_call_value(script_ctx_t*,IDispatch*,IDispatch*,WORD,unsigned,jsval_t*,jsval_t*) DECLSPEC_HIDDEN;
+HRESULT jsdisp_call_value(jsdisp_t*,IDispatch*,WORD,unsigned,jsval_t*,jsval_t*) DECLSPEC_HIDDEN;
+HRESULT jsdisp_call(jsdisp_t*,DISPID,WORD,unsigned,jsval_t*,jsval_t*) DECLSPEC_HIDDEN;
+HRESULT jsdisp_call_name(jsdisp_t*,const WCHAR*,WORD,unsigned,jsval_t*,jsval_t*) DECLSPEC_HIDDEN;
+HRESULT disp_propget(script_ctx_t*,IDispatch*,DISPID,jsval_t*) DECLSPEC_HIDDEN;
+HRESULT disp_propput(script_ctx_t*,IDispatch*,DISPID,jsval_t) DECLSPEC_HIDDEN;
+HRESULT jsdisp_propget(jsdisp_t*,DISPID,jsval_t*) DECLSPEC_HIDDEN;
+HRESULT jsdisp_propput(jsdisp_t*,const WCHAR*,DWORD,jsval_t) DECLSPEC_HIDDEN;
+HRESULT jsdisp_propput_name(jsdisp_t*,const WCHAR*,jsval_t) DECLSPEC_HIDDEN;
+HRESULT jsdisp_propput_const(jsdisp_t*,const WCHAR*,jsval_t) DECLSPEC_HIDDEN;
+HRESULT jsdisp_propput_dontenum(jsdisp_t*,const WCHAR*,jsval_t) DECLSPEC_HIDDEN;
+HRESULT jsdisp_propput_idx(jsdisp_t*,DWORD,jsval_t) DECLSPEC_HIDDEN;
+HRESULT jsdisp_propget_name(jsdisp_t*,LPCWSTR,jsval_t*) DECLSPEC_HIDDEN;
+HRESULT jsdisp_get_idx(jsdisp_t*,DWORD,jsval_t*) DECLSPEC_HIDDEN;
+HRESULT jsdisp_get_id(jsdisp_t*,const WCHAR*,DWORD,DISPID*) DECLSPEC_HIDDEN;
+HRESULT disp_delete(IDispatch*,DISPID,BOOL*) DECLSPEC_HIDDEN;
+HRESULT disp_delete_name(script_ctx_t*,IDispatch*,jsstr_t*,BOOL*);
+HRESULT jsdisp_delete_idx(jsdisp_t*,DWORD) DECLSPEC_HIDDEN;
+HRESULT jsdisp_is_own_prop(jsdisp_t*,const WCHAR*,BOOL*) DECLSPEC_HIDDEN;
+HRESULT jsdisp_is_enumerable(jsdisp_t*,const WCHAR*,BOOL*) DECLSPEC_HIDDEN;
HRESULT create_builtin_function(script_ctx_t*,builtin_invoke_t,const WCHAR*,const builtin_info_t*,DWORD,
- DispatchEx*,DispatchEx**);
-HRESULT Function_value(script_ctx_t*,vdisp_t*,WORD,DISPPARAMS*,VARIANT*,jsexcept_t*,IServiceProvider*);
-
-HRESULT throw_eval_error(script_ctx_t*,jsexcept_t*,UINT,const WCHAR*);
-HRESULT throw_generic_error(script_ctx_t*,jsexcept_t*,UINT,const WCHAR*);
-HRESULT throw_range_error(script_ctx_t*,jsexcept_t*,UINT,const WCHAR*);
-HRESULT throw_reference_error(script_ctx_t*,jsexcept_t*,UINT,const WCHAR*);
-HRESULT throw_regexp_error(script_ctx_t*,jsexcept_t*,UINT,const WCHAR*);
-HRESULT throw_syntax_error(script_ctx_t*,jsexcept_t*,UINT,const WCHAR*);
-HRESULT throw_type_error(script_ctx_t*,jsexcept_t*,UINT,const WCHAR*);
-HRESULT throw_uri_error(script_ctx_t*,jsexcept_t*,UINT,const WCHAR*);
-
-HRESULT create_object(script_ctx_t*,DispatchEx*,DispatchEx**);
-HRESULT create_math(script_ctx_t*,DispatchEx**);
-HRESULT create_array(script_ctx_t*,DWORD,DispatchEx**);
-HRESULT create_regexp(script_ctx_t*,const WCHAR *,int,DWORD,DispatchEx**);
-HRESULT create_regexp_var(script_ctx_t*,VARIANT*,VARIANT*,DispatchEx**);
-HRESULT create_string(script_ctx_t*,const WCHAR*,DWORD,DispatchEx**);
-HRESULT create_bool(script_ctx_t*,VARIANT_BOOL,DispatchEx**);
-HRESULT create_number(script_ctx_t*,VARIANT*,DispatchEx**);
+ jsdisp_t*,jsdisp_t**) DECLSPEC_HIDDEN;
+HRESULT create_builtin_constructor(script_ctx_t*,builtin_invoke_t,const WCHAR*,const builtin_info_t*,DWORD,
+ jsdisp_t*,jsdisp_t**) DECLSPEC_HIDDEN;
+HRESULT Function_value(script_ctx_t*,vdisp_t*,WORD,unsigned,jsval_t*,jsval_t*) DECLSPEC_HIDDEN;
+HRESULT Function_invoke(jsdisp_t*,IDispatch*,WORD,unsigned,jsval_t*,jsval_t*) DECLSPEC_HIDDEN;
+
+HRESULT throw_eval_error(script_ctx_t*,HRESULT,const WCHAR*) DECLSPEC_HIDDEN;
+HRESULT throw_generic_error(script_ctx_t*,HRESULT,const WCHAR*) DECLSPEC_HIDDEN;
+HRESULT throw_range_error(script_ctx_t*,HRESULT,const WCHAR*) DECLSPEC_HIDDEN;
+HRESULT throw_reference_error(script_ctx_t*,HRESULT,const WCHAR*) DECLSPEC_HIDDEN;
+HRESULT throw_regexp_error(script_ctx_t*,HRESULT,const WCHAR*) DECLSPEC_HIDDEN;
+HRESULT throw_syntax_error(script_ctx_t*,HRESULT,const WCHAR*) DECLSPEC_HIDDEN;
+HRESULT throw_type_error(script_ctx_t*,HRESULT,const WCHAR*) DECLSPEC_HIDDEN;
+HRESULT throw_uri_error(script_ctx_t*,HRESULT,const WCHAR*) DECLSPEC_HIDDEN;
+
+HRESULT create_object(script_ctx_t*,jsdisp_t*,jsdisp_t**) DECLSPEC_HIDDEN;
+HRESULT create_math(script_ctx_t*,jsdisp_t**) DECLSPEC_HIDDEN;
+HRESULT create_array(script_ctx_t*,DWORD,jsdisp_t**) DECLSPEC_HIDDEN;
+HRESULT create_regexp(script_ctx_t*,jsstr_t*,DWORD,jsdisp_t**) DECLSPEC_HIDDEN;
+HRESULT create_regexp_var(script_ctx_t*,jsval_t,jsval_t*,jsdisp_t**) DECLSPEC_HIDDEN;
+HRESULT create_string(script_ctx_t*,jsstr_t*,jsdisp_t**) DECLSPEC_HIDDEN;
+HRESULT create_bool(script_ctx_t*,BOOL,jsdisp_t**) DECLSPEC_HIDDEN;
+HRESULT create_number(script_ctx_t*,double,jsdisp_t**) DECLSPEC_HIDDEN;
+HRESULT create_vbarray(script_ctx_t*,SAFEARRAY*,jsdisp_t**) DECLSPEC_HIDDEN;
typedef enum {
NO_HINT,
HINT_NUMBER
} hint_t;
-HRESULT to_primitive(script_ctx_t*,VARIANT*,jsexcept_t*,VARIANT*, hint_t);
-HRESULT to_boolean(VARIANT*,VARIANT_BOOL*);
-HRESULT to_number(script_ctx_t*,VARIANT*,jsexcept_t*,VARIANT*);
-HRESULT to_integer(script_ctx_t*,VARIANT*,jsexcept_t*,VARIANT*);
-HRESULT to_int32(script_ctx_t*,VARIANT*,jsexcept_t*,INT*);
-HRESULT to_uint32(script_ctx_t*,VARIANT*,jsexcept_t*,DWORD*);
-HRESULT to_string(script_ctx_t*,VARIANT*,jsexcept_t*,BSTR*);
-HRESULT to_object(script_ctx_t*,VARIANT*,IDispatch**);
+HRESULT to_primitive(script_ctx_t*,jsval_t,jsval_t*, hint_t) DECLSPEC_HIDDEN;
+HRESULT to_boolean(jsval_t,BOOL*) DECLSPEC_HIDDEN;
+HRESULT to_number(script_ctx_t*,jsval_t,double*) DECLSPEC_HIDDEN;
+HRESULT to_integer(script_ctx_t*,jsval_t,double*) DECLSPEC_HIDDEN;
+HRESULT to_int32(script_ctx_t*,jsval_t,INT*) DECLSPEC_HIDDEN;
+HRESULT to_uint32(script_ctx_t*,jsval_t,UINT32*) DECLSPEC_HIDDEN;
+HRESULT to_string(script_ctx_t*,jsval_t,jsstr_t**) DECLSPEC_HIDDEN;
+HRESULT to_object(script_ctx_t*,jsval_t,IDispatch**) DECLSPEC_HIDDEN;
+
+HRESULT variant_change_type(script_ctx_t*,VARIANT*,VARIANT*,VARTYPE) DECLSPEC_HIDDEN;
+
+HRESULT decode_source(WCHAR*) DECLSPEC_HIDDEN;
+
+HRESULT double_to_string(double,jsstr_t**) DECLSPEC_HIDDEN;
typedef struct named_item_t {
IDispatch *disp;
struct named_item_t *next;
} named_item_t;
+typedef struct _cc_var_t cc_var_t;
+
+typedef struct {
+ cc_var_t *vars;
+} cc_ctx_t;
+
+void release_cc(cc_ctx_t*) DECLSPEC_HIDDEN;
+
+typedef struct {
+ IServiceProvider IServiceProvider_iface;
+
+ LONG ref;
+
+ script_ctx_t *ctx;
+} JSCaller;
+
+#include "jsval.h"
+
+typedef struct {
+ EXCEPINFO ei;
+ jsval_t val;
+} jsexcept_t;
+
+typedef struct {
+ unsigned index;
+ unsigned length;
+} match_result_t;
+
struct _script_ctx_t {
LONG ref;
SCRIPTSTATE state;
+ IActiveScript *active_script;
+
exec_ctx_t *exec_ctx;
named_item_t *named_items;
IActiveScriptSite *site;
DWORD safeopt;
DWORD version;
LCID lcid;
+ cc_ctx_t *cc;
+ JSCaller *jscaller;
+ jsexcept_t ei;
- jsheap_t tmp_heap;
+ heap_pool_t tmp_heap;
IDispatch *host_global;
- BSTR last_match;
+ jsstr_t *last_match;
+ match_result_t match_parens[9];
DWORD last_match_index;
DWORD last_match_length;
- DispatchEx *global;
- DispatchEx *function_constr;
- DispatchEx *activex_constr;
- DispatchEx *array_constr;
- DispatchEx *bool_constr;
- DispatchEx *date_constr;
- DispatchEx *error_constr;
- DispatchEx *eval_error_constr;
- DispatchEx *range_error_constr;
- DispatchEx *reference_error_constr;
- DispatchEx *regexp_error_constr;
- DispatchEx *syntax_error_constr;
- DispatchEx *type_error_constr;
- DispatchEx *uri_error_constr;
- DispatchEx *number_constr;
- DispatchEx *object_constr;
- DispatchEx *regexp_constr;
- DispatchEx *string_constr;
+ jsdisp_t *global;
+ jsdisp_t *function_constr;
+ jsdisp_t *activex_constr;
+ jsdisp_t *array_constr;
+ jsdisp_t *bool_constr;
+ jsdisp_t *date_constr;
+ jsdisp_t *error_constr;
+ jsdisp_t *eval_error_constr;
+ jsdisp_t *range_error_constr;
+ jsdisp_t *reference_error_constr;
+ jsdisp_t *regexp_error_constr;
+ jsdisp_t *syntax_error_constr;
+ jsdisp_t *type_error_constr;
+ jsdisp_t *uri_error_constr;
+ jsdisp_t *number_constr;
+ jsdisp_t *object_constr;
+ jsdisp_t *regexp_constr;
+ jsdisp_t *string_constr;
+ jsdisp_t *vbarray_constr;
};
-void script_release(script_ctx_t*);
+void script_release(script_ctx_t*) DECLSPEC_HIDDEN;
+void clear_ei(script_ctx_t*) DECLSPEC_HIDDEN;
static inline void script_addref(script_ctx_t *ctx)
{
ctx->ref++;
}
-HRESULT init_global(script_ctx_t*);
-HRESULT init_function_constr(script_ctx_t*,DispatchEx*);
-HRESULT create_object_prototype(script_ctx_t*,DispatchEx**);
+HRESULT init_global(script_ctx_t*) DECLSPEC_HIDDEN;
+HRESULT init_function_constr(script_ctx_t*,jsdisp_t*) DECLSPEC_HIDDEN;
+HRESULT create_object_prototype(script_ctx_t*,jsdisp_t**) DECLSPEC_HIDDEN;
-HRESULT create_activex_constr(script_ctx_t*,DispatchEx**);
-HRESULT create_array_constr(script_ctx_t*,DispatchEx*,DispatchEx**);
-HRESULT create_bool_constr(script_ctx_t*,DispatchEx*,DispatchEx**);
-HRESULT create_date_constr(script_ctx_t*,DispatchEx*,DispatchEx**);
-HRESULT init_error_constr(script_ctx_t*,DispatchEx*);
-HRESULT create_number_constr(script_ctx_t*,DispatchEx*,DispatchEx**);
-HRESULT create_object_constr(script_ctx_t*,DispatchEx*,DispatchEx**);
-HRESULT create_regexp_constr(script_ctx_t*,DispatchEx*,DispatchEx**);
-HRESULT create_string_constr(script_ctx_t*,DispatchEx*,DispatchEx**);
+HRESULT create_activex_constr(script_ctx_t*,jsdisp_t**) DECLSPEC_HIDDEN;
+HRESULT create_array_constr(script_ctx_t*,jsdisp_t*,jsdisp_t**) DECLSPEC_HIDDEN;
+HRESULT create_bool_constr(script_ctx_t*,jsdisp_t*,jsdisp_t**) DECLSPEC_HIDDEN;
+HRESULT create_date_constr(script_ctx_t*,jsdisp_t*,jsdisp_t**) DECLSPEC_HIDDEN;
+HRESULT init_error_constr(script_ctx_t*,jsdisp_t*) DECLSPEC_HIDDEN;
+HRESULT create_number_constr(script_ctx_t*,jsdisp_t*,jsdisp_t**) DECLSPEC_HIDDEN;
+HRESULT create_object_constr(script_ctx_t*,jsdisp_t*,jsdisp_t**) DECLSPEC_HIDDEN;
+HRESULT create_regexp_constr(script_ctx_t*,jsdisp_t*,jsdisp_t**) DECLSPEC_HIDDEN;
+HRESULT create_string_constr(script_ctx_t*,jsdisp_t*,jsdisp_t**) DECLSPEC_HIDDEN;
+HRESULT create_vbarray_constr(script_ctx_t*,jsdisp_t*,jsdisp_t**) DECLSPEC_HIDDEN;
-IUnknown *create_ax_site(script_ctx_t*);
-
-typedef struct {
- const WCHAR *str;
- DWORD len;
-} match_result_t;
+IUnknown *create_ax_site(script_ctx_t*) DECLSPEC_HIDDEN;
+HRESULT create_jscaller(script_ctx_t*) DECLSPEC_HIDDEN;
#define REM_CHECK_GLOBAL 0x0001
#define REM_RESET_INDEX 0x0002
#define REM_NO_CTX_UPDATE 0x0004
-HRESULT regexp_match_next(script_ctx_t*,DispatchEx*,DWORD,const WCHAR*,DWORD,const WCHAR**,match_result_t**,
- DWORD*,DWORD*,match_result_t*);
-HRESULT regexp_match(script_ctx_t*,DispatchEx*,const WCHAR*,DWORD,BOOL,match_result_t**,DWORD*);
-HRESULT parse_regexp_flags(const WCHAR*,DWORD,DWORD*);
-HRESULT regexp_string_match(script_ctx_t*,DispatchEx*,BSTR,VARIANT*,jsexcept_t*);
-
-static inline VARIANT *get_arg(DISPPARAMS *dp, DWORD i)
-{
- return dp->rgvarg + dp->cArgs-i-1;
-}
-
-static inline DWORD arg_cnt(const DISPPARAMS *dp)
-{
- return dp->cArgs - dp->cNamedArgs;
-}
-
-static inline BOOL is_class(DispatchEx *jsdisp, jsclass_t class)
+#define REM_ALLOC_RESULT 0x0008
+#define REM_NO_PARENS 0x0010
+struct match_state_t;
+HRESULT regexp_match_next(script_ctx_t*,jsdisp_t*,DWORD,jsstr_t*,struct match_state_t**) DECLSPEC_HIDDEN;
+HRESULT parse_regexp_flags(const WCHAR*,DWORD,DWORD*) DECLSPEC_HIDDEN;
+HRESULT regexp_string_match(script_ctx_t*,jsdisp_t*,jsstr_t*,jsval_t*) DECLSPEC_HIDDEN;
+
+static inline BOOL is_class(jsdisp_t *jsdisp, jsclass_t class)
{
return jsdisp->builtin_info->class == class;
}
return is_jsdisp(vdisp) && is_class(vdisp->u.jsdisp, class);
}
-static inline BOOL is_num_vt(enum VARENUM vt)
-{
- return vt == VT_I4 || vt == VT_R8;
-}
-
-static inline DOUBLE num_val(const VARIANT *v)
-{
- return V_VT(v) == VT_I4 ? V_I4(v) : V_R8(v);
-}
-
-static inline void num_set_val(VARIANT *v, DOUBLE d)
-{
- if(d == (DOUBLE)(INT)d) {
- V_VT(v) = VT_I4;
- V_I4(v) = d;
- }else {
- V_VT(v) = VT_R8;
- V_R8(v) = d;
- }
-}
+#ifndef INT32_MIN
+#define INT32_MIN (-2147483647-1)
+#endif
-static inline void num_set_nan(VARIANT *v)
-{
- V_VT(v) = VT_R8;
-#ifdef NAN
- V_R8(v) = NAN;
-#else
- V_UI8(v) = (ULONGLONG)0x7ff80000<<32;
+#ifndef INT32_MAX
+#define INT32_MAX (2147483647)
#endif
-}
-static inline DOUBLE ret_nan(void)
+static inline BOOL is_int32(double d)
{
- VARIANT v;
- num_set_nan(&v);
- return V_R8(&v);
+ return INT32_MIN <= d && d <= INT32_MAX && (double)(int)d == d;
}
-static inline void num_set_inf(VARIANT *v, BOOL positive)
+static inline DWORD make_grfdex(script_ctx_t *ctx, DWORD flags)
{
- V_VT(v) = VT_R8;
-#ifdef INFINITY
- V_R8(v) = positive ? INFINITY : -INFINITY;
-#else
- V_UI8(v) = (ULONGLONG)0x7ff00000<<32;
- if(!positive)
- V_R8(v) = -V_R8(v);
-#endif
+ return (ctx->version << 28) | flags;
}
-static inline DWORD make_grfdex(script_ctx_t *ctx, DWORD flags)
+#define FACILITY_JSCRIPT 10
+
+#define MAKE_JSERROR(code) MAKE_HRESULT(SEVERITY_ERROR, FACILITY_JSCRIPT, code)
+
+#define JS_E_TO_PRIMITIVE MAKE_JSERROR(IDS_TO_PRIMITIVE)
+#define JS_E_INVALIDARG MAKE_JSERROR(IDS_INVALID_CALL_ARG)
+#define JS_E_SUBSCRIPT_OUT_OF_RANGE MAKE_JSERROR(IDS_SUBSCRIPT_OUT_OF_RANGE)
+#define JS_E_OBJECT_REQUIRED MAKE_JSERROR(IDS_OBJECT_REQUIRED)
+#define JS_E_CANNOT_CREATE_OBJ MAKE_JSERROR(IDS_CREATE_OBJ_ERROR)
+#define JS_E_INVALID_PROPERTY MAKE_JSERROR(IDS_NO_PROPERTY)
+#define JS_E_INVALID_ACTION MAKE_JSERROR(IDS_UNSUPPORTED_ACTION)
+#define JS_E_MISSING_ARG MAKE_JSERROR(IDS_ARG_NOT_OPT)
+#define JS_E_SYNTAX MAKE_JSERROR(IDS_SYNTAX_ERROR)
+#define JS_E_MISSING_SEMICOLON MAKE_JSERROR(IDS_SEMICOLON)
+#define JS_E_MISSING_LBRACKET MAKE_JSERROR(IDS_LBRACKET)
+#define JS_E_MISSING_RBRACKET MAKE_JSERROR(IDS_RBRACKET)
+#define JS_E_INVALID_CHAR MAKE_JSERROR(IDS_INVALID_CHAR)
+#define JS_E_UNTERMINATED_STRING MAKE_JSERROR(IDS_UNTERMINATED_STR)
+#define JS_E_MISPLACED_RETURN MAKE_JSERROR(IDS_MISPLACED_RETURN)
+#define JS_E_INVALID_BREAK MAKE_JSERROR(IDS_INVALID_BREAK)
+#define JS_E_INVALID_CONTINUE MAKE_JSERROR(IDS_INVALID_CONTINUE)
+#define JS_E_LABEL_REDEFINED MAKE_JSERROR(IDS_LABEL_REDEFINED)
+#define JS_E_LABEL_NOT_FOUND MAKE_JSERROR(IDS_LABEL_NOT_FOUND)
+#define JS_E_DISABLED_CC MAKE_JSERROR(IDS_DISABLED_CC)
+#define JS_E_FUNCTION_EXPECTED MAKE_JSERROR(IDS_NOT_FUNC)
+#define JS_E_DATE_EXPECTED MAKE_JSERROR(IDS_NOT_DATE)
+#define JS_E_NUMBER_EXPECTED MAKE_JSERROR(IDS_NOT_NUM)
+#define JS_E_OBJECT_EXPECTED MAKE_JSERROR(IDS_OBJECT_EXPECTED)
+#define JS_E_ILLEGAL_ASSIGN MAKE_JSERROR(IDS_ILLEGAL_ASSIGN)
+#define JS_E_UNDEFINED_VARIABLE MAKE_JSERROR(IDS_UNDEFINED)
+#define JS_E_BOOLEAN_EXPECTED MAKE_JSERROR(IDS_NOT_BOOL)
+#define JS_E_VBARRAY_EXPECTED MAKE_JSERROR(IDS_NOT_VBARRAY)
+#define JS_E_INVALID_DELETE MAKE_JSERROR(IDS_INVALID_DELETE)
+#define JS_E_JSCRIPT_EXPECTED MAKE_JSERROR(IDS_JSCRIPT_EXPECTED)
+#define JS_E_REGEXP_SYNTAX MAKE_JSERROR(IDS_REGEXP_SYNTAX_ERROR)
+#define JS_E_INVALID_URI_CODING MAKE_JSERROR(IDS_URI_INVALID_CODING)
+#define JS_E_INVALID_URI_CHAR MAKE_JSERROR(IDS_URI_INVALID_CHAR)
+#define JS_E_FRACTION_DIGITS_OUT_OF_RANGE MAKE_JSERROR(IDS_FRACTION_DIGITS_OUT_OF_RANGE)
+#define JS_E_PRECISION_OUT_OF_RANGE MAKE_JSERROR(IDS_PRECISION_OUT_OF_RANGE)
+#define JS_E_INVALID_LENGTH MAKE_JSERROR(IDS_INVALID_LENGTH)
+#define JS_E_ARRAY_EXPECTED MAKE_JSERROR(IDS_ARRAY_EXPECTED)
+
+static inline BOOL is_jscript_error(HRESULT hres)
{
- return (ctx->version << 28) | flags;
+ return HRESULT_FACILITY(hres) == FACILITY_JSCRIPT;
}
-const char *debugstr_variant(const VARIANT*);
+const char *debugstr_variant(const VARIANT*) DECLSPEC_HIDDEN;
+const char *debugstr_jsval(const jsval_t) DECLSPEC_HIDDEN;
-HRESULT WINAPI JScriptFactory_CreateInstance(IClassFactory*,IUnknown*,REFIID,void**);
+HRESULT create_jscript_object(BOOL,REFIID,void**) DECLSPEC_HIDDEN;
-extern LONG module_ref;
+extern LONG module_ref DECLSPEC_HIDDEN;
static inline void lock_module(void)
{
{
InterlockedDecrement(&module_ref);
}
-
-static inline void *heap_alloc(size_t len)
-{
- return HeapAlloc(GetProcessHeap(), 0, len);
-}
-
-static inline void *heap_alloc_zero(size_t len)
-{
- return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
-}
-
-static inline void *heap_realloc(void *mem, size_t len)
-{
- return HeapReAlloc(GetProcessHeap(), 0, mem, len);
-}
-
-static inline BOOL heap_free(void *mem)
-{
- return HeapFree(GetProcessHeap(), 0, mem);
-}
-
-static inline LPWSTR heap_strdupW(LPCWSTR str)
-{
- LPWSTR ret = NULL;
-
- if(str) {
- DWORD size;
-
- size = (strlenW(str)+1)*sizeof(WCHAR);
- ret = heap_alloc(size);
- memcpy(ret, str, size);
- }
-
- return ret;
-}
-
-#define DEFINE_THIS(cls,ifc,iface) ((cls*)((BYTE*)(iface)-offsetof(cls,lp ## ifc ## Vtbl)))
+++ /dev/null
-[version]
-Signature="$CHICAGO$"
-
-
-[RegisterDll]
-AddReg=Classes.Reg
-
-
-[UnregisterDll]
-DelReg=Classes.Reg
-
-
-[Classes.Reg]
-HKCR,"CLSID\%CLSID_JScript%",,,"JScript Language"
-HKCR,"CLSID\%CLSID_JScript%\Implemented Categories\%CATID_ActiveScript%",,16
-HKCR,"CLSID\%CLSID_JScript%\Implemented Categories\%CATID_ActiveScriptParse%",,16
-HKCR,"CLSID\%CLSID_JScript%\InprocServer32",,,"%MODULE%"
-HKCR,"CLSID\%CLSID_JScript%\InprocServer32","ThreadingModel",,"Both"
-HKCR,"CLSID\%CLSID_JScript%\OLEScript",,16
-HKCR,"CLSID\%CLSID_JScript%\ProgID",,,"JScript"
-
-HKCR,"CLSID\%CLSID_JScriptAuthor%",,,"JScript Language Authoring"
-HKCR,"CLSID\%CLSID_JScriptAuthor%\Implemented Categories\%CATID_ActiveScriptAuthor%",,16
-HKCR,"CLSID\%CLSID_JScriptAuthor%\InprocServer32",,,"%MODULE%"
-HKCR,"CLSID\%CLSID_JScriptAuthor%\InprocServer32","ThreadingModel",,"Both"
-HKCR,"CLSID\%CLSID_JScriptAuthor%\OLEScript",,16
-HKCR,"CLSID\%CLSID_JScriptAuthor%\ProgID",,,"JScript Author"
-
-HKCR,"CLSID\%CLSID_JScriptEncode%",,,"JScript Language Encoding"
-HKCR,"CLSID\%CLSID_JScriptEncode%\Implemented Categories\%CATID_ActiveScript%",,16
-HKCR,"CLSID\%CLSID_JScriptEncode%\Implemented Categories\%CATID_ActiveScriptParse%",,16
-HKCR,"CLSID\%CLSID_JScriptEncode%\Implemented Categories\%CATID_ActiveScriptEncode%",,16
-HKCR,"CLSID\%CLSID_JScriptEncode%\InprocServer32",,,"%MODULE%"
-HKCR,"CLSID\%CLSID_JScriptEncode%\InprocServer32","ThreadingModel",,"Both"
-HKCR,"CLSID\%CLSID_JScriptEncode%\OLEScript",,16
-HKCR,"CLSID\%CLSID_JScriptEncode%\ProgID",,,"JScript.Encode"
-
-HKCR,"Component Categories\%CATID_ActiveScriptAuthor%","409",,"Active Scripting Engine with Authoring"
-HKCR,"Component Categories\%CATID_ActiveScript%","409",,"Active Scripting Engine"
-HKCR,"Component Categories\%CATID_ActiveScriptParse%","409",,"Active Scripting Engine with Parsing"
-HKCR,"Component Categories\%CATID_ActiveScriptEncode%","409",,"Active Scripting Engine with Encoding"
-
-HKCR,"ECMAScript",,,"JScript Language"
-HKCR,"ECMAScript\CLSID",,,"%CLSID_JScript%"
-HKCR,"ECMAScript\OLEScript",,16
-
-HKCR,"JavaScript",,,"JScript Language"
-HKCR,"JavaScript\CLSID",,,"%CLSID_JScript%"
-HKCR,"JavaScript\OLEScript",,16
-
-HKCR,"JavaScript Author",,,"JScript Language Authoring"
-HKCR,"JavaScript Author\CLSID",,,"%CLSID_JScriptAuthor%"
-HKCR,"JavaScript Author\OLEScript",,16
-
-HKCR,"JavaScript1.1",,,"JScript Language"
-HKCR,"JavaScript1.1\CLSID",,,"%CLSID_JScript%"
-HKCR,"JavaScript1.1\OLEScript",,16
-
-HKCR,"JavaScript1.1 Author",,,"JScript Language Authoring"
-HKCR,"JavaScript1.1 Author\CLSID",,,"%CLSID_JScriptAuthor%"
-HKCR,"JavaScript1.1 Author\OLEScript",,16
-
-HKCR,"JavaScript1.2",,,"JScript Language"
-HKCR,"JavaScript1.2\CLSID",,,"%CLSID_JScript%"
-HKCR,"JavaScript1.2\OLEScript",,16
-
-HKCR,"JavaScript1.2 Author",,,"JScript Language Authoring"
-HKCR,"JavaScript1.2 Author\CLSID",,,"%CLSID_JScriptAuthor%"
-HKCR,"JavaScript1.2 Author\OLEScript",,16
-
-HKCR,"JavaScript1.3",,,"JScript Language"
-HKCR,"JavaScript1.3\CLSID",,,"%CLSID_JScript%"
-HKCR,"JavaScript1.3\OLEScript",,16
-
-HKCR,"JScript",,,"JScript Language"
-HKCR,"JScript\CLSID",,,"%CLSID_JScript%"
-HKCR,"JScript\OLEScript",,16
-
-HKCR,"JScript Author",,,"JScript Language Authoring"
-HKCR,"JScript Author\CLSID",,,"%CLSID_JScriptAuthor%"
-HKCR,"JScript Author\OLEScript",,16
-
-HKCR,"JScript.Encode",,,"JScript Language Encoding"
-HKCR,"JScript.Encode\CLSID",,,"%CLSID_JScriptEncode%"
-HKCR,"JScript.Encode\OLEScript",,16
-
-HKCR,"LiveScript",,,"JScript Language"
-HKCR,"LiveScript\CLSID",,,"%CLSID_JScript%"
-HKCR,"LiveScript\OLEScript",,16
-
-HKCR,"LiveScript Author",,,"JScript Language Authoring"
-HKCR,"LiveScript Author\CLSID",,,"%CLSID_JScriptAuthor%"
-HKCR,"LiveScript Author\OLEScript",,16
-
-
-[Strings]
-MODULE="jscript.dll"
--- /dev/null
+/*
+ * Copyright 2009 Piotr Caban
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "resource.h"
+
+LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT
+
+STRINGTABLE
+{
+ IDS_TO_PRIMITIVE "Error converting object to primitive type"
+ IDS_INVALID_CALL_ARG "Invalid procedure call or argument"
+ IDS_SUBSCRIPT_OUT_OF_RANGE "Subscript out of range"
+ IDS_OBJECT_REQUIRED "Object required"
+ IDS_CREATE_OBJ_ERROR "Automation server can't create object"
+ IDS_NO_PROPERTY "Object doesn't support this property or method"
+ IDS_UNSUPPORTED_ACTION "Object doesn't support this action"
+ IDS_ARG_NOT_OPT "Argument not optional"
+ IDS_SYNTAX_ERROR "Syntax error"
+ IDS_SEMICOLON "Expected ';'"
+ IDS_LBRACKET "Expected '('"
+ IDS_RBRACKET "Expected ')'"
+ IDS_INVALID_CHAR "Invalid character"
+ IDS_UNTERMINATED_STR "Unterminated string constant"
+ IDS_MISPLACED_RETURN "'return' statement outside of function"
+ IDS_INVALID_BREAK "Can't have 'break' outside of loop"
+ IDS_INVALID_CONTINUE "Can't have 'continue' outside of loop"
+ IDS_LABEL_REDEFINED "Label redefined"
+ IDS_LABEL_NOT_FOUND "Label not found"
+ IDS_DISABLED_CC "Conditional compilation is turned off"
+ IDS_NOT_FUNC "Function expected"
+ IDS_NOT_DATE "'[object]' is not a date object"
+ IDS_NOT_NUM "Number expected"
+ IDS_OBJECT_EXPECTED "Object expected"
+ IDS_ILLEGAL_ASSIGN "Illegal assignment"
+ IDS_UNDEFINED "'|' is undefined"
+ IDS_NOT_BOOL "Boolean object expected"
+ IDS_INVALID_DELETE "Cannot delete '|'"
+ IDS_NOT_VBARRAY "VBArray object expected"
+ IDS_JSCRIPT_EXPECTED "JScript object expected"
+ IDS_REGEXP_SYNTAX_ERROR "Syntax error in regular expression"
+ IDS_URI_INVALID_CODING "URI to be decoded is incorrect"
+ IDS_URI_INVALID_CHAR "URI to be encoded contains invalid characters"
+ IDS_FRACTION_DIGITS_OUT_OF_RANGE "Number of fraction digits is out of range"
+ IDS_PRECISION_OUT_OF_RANGE "Precision is out of range"
+ IDS_INVALID_LENGTH "Array length must be a finite positive integer"
+ IDS_ARRAY_EXPECTED "Array object expected"
+}
+
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+
+/* @makedep: jscript.rgs */
+2 WINE_REGISTRY jscript.rgs
+
+3 WINE_REGISTRY jscript_classes.rgs
+
+#define WINE_FILEDESCRIPTION_STR "Wine JScript"
+#define WINE_FILENAME_STR "jscript.dll"
+#define WINE_FILEVERSION 5,7,7601,16982
+#define WINE_FILEVERSION_STR "5.8.7601.16982"
+#define WINE_PRODUCTVERSION 5,8,7601,16982
+#define WINE_PRODUCTVERSION_STR "5.8.7601.16982"
+
+#include "wine/wine_common_ver.rc"
--- /dev/null
+HKCR
+{
+ NoRemove CLSID
+ {
+ '{F414C260-6AC0-11CF-B6D1-00AA00BBBB58}'
+ {
+ 'Implemented Categories'
+ {
+ '{f0b7a1a1-9847-11cf-8f20-00805f2cd064}'
+ '{f0b7a1a2-9847-11cf-8f20-00805f2cd064}'
+ }
+ OLEScript
+ }
+ '{F414C261-6AC0-11CF-B6D1-00AA00BBBB58}'
+ {
+ 'Implemented Categories'
+ {
+ '{0aee2a92-bcbb-11d0-8c72-00c04fc2b085}'
+ }
+ OLEScript
+ }
+ '{F414C262-6AC0-11CF-B6D1-00AA00BBBB58}'
+ {
+ 'Implemented Categories'
+ {
+ '{f0b7a1a1-9847-11cf-8f20-00805f2cd064}'
+ '{f0b7a1a2-9847-11cf-8f20-00805f2cd064}'
+ '{f0b7a1a3-9847-11cf-8f20-00805f2cd064}'
+ }
+ OLEScript
+ }
+ }
+
+ NoRemove 'Component Categories'
+ {
+ ForceRemove '{f0b7a1a1-9847-11cf-8f20-00805f2cd064}'
+ {
+ val '409' = s 'Active Scripting Engine'
+ }
+ ForceRemove '{f0b7a1a2-9847-11cf-8f20-00805f2cd064}'
+ {
+ val '409' = s 'Active Scripting Engine with Parsing'
+ }
+ ForceRemove '{f0b7a1a3-9847-11cf-8f20-00805f2cd064}'
+ {
+ val '409' = s 'Active Scripting Engine with Encoding'
+ }
+ ForceRemove '{0aee2a92-bcbb-11d0-8c72-00c04fc2b085}'
+ {
+ val '409' = s 'Active Scripting Engine with Authoring'
+ }
+ }
+
+ 'ECMAScript' = s 'JScript Language'
+ {
+ CLSID = s '{F414C260-6AC0-11CF-B6D1-00AA00BBBB58}'
+ OLEScript
+ }
+ 'JavaScript' = s 'JScript Language'
+ {
+ CLSID = s '{F414C260-6AC0-11CF-B6D1-00AA00BBBB58}'
+ OLEScript
+ }
+ 'JavaScript1.1' = s 'JScript Language'
+ {
+ CLSID = s '{F414C260-6AC0-11CF-B6D1-00AA00BBBB58}'
+ OLEScript
+ }
+ 'JavaScript1.2' = s 'JScript Language'
+ {
+ CLSID = s '{F414C260-6AC0-11CF-B6D1-00AA00BBBB58}'
+ OLEScript
+ }
+ 'JavaScript1.3' = s 'JScript Language'
+ {
+ CLSID = s '{F414C260-6AC0-11CF-B6D1-00AA00BBBB58}'
+ OLEScript
+ }
+ 'LiveScript' = s 'JScript Language'
+ {
+ CLSID = s '{F414C260-6AC0-11CF-B6D1-00AA00BBBB58}'
+ OLEScript
+ }
+ 'JScript'
+ {
+ OLEScript
+ }
+
+ 'JScript Author'
+ {
+ OLEScript
+ }
+ 'JavaScript Author' = s 'JScript Language Authoring'
+ {
+ CLSID = s '{F414C261-6AC0-11CF-B6D1-00AA00BBBB58}'
+ OLEScript
+ }
+ 'JavaScript1.1 Author' = s 'JScript Language Authoring'
+ {
+ CLSID = s '{F414C261-6AC0-11CF-B6D1-00AA00BBBB58}'
+ OLEScript
+ }
+ 'JavaScript1.2 Author' = s 'JScript Language Authoring'
+ {
+ CLSID = s '{F414C261-6AC0-11CF-B6D1-00AA00BBBB58}'
+ OLEScript
+ }
+ 'LiveScript Author' = s 'JScript Language Authoring'
+ {
+ CLSID = s '{F414C261-6AC0-11CF-B6D1-00AA00BBBB58}'
+ OLEScript
+ }
+
+ 'JScript.Encode'
+ {
+ OLEScript
+ }
+
+ ForceRemove JSFile = s 'JScript Script File'
+ {
+ ScriptEngine = s 'JScript'
+ }
+}
--- /dev/null
+/*
+ * Copyright 2010 Jacek Caban for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+[
+ helpstring("JScript Language"),
+ threading(both),
+ progid("JScript"),
+ uuid(f414c260-6ac0-11cf-b6d1-00aa00bbbb58)
+]
+coclass JScript {}
+
+[
+ helpstring("JScript Language Authoring"),
+ threading(both),
+ progid("JScript Author"),
+ uuid(f414c261-6ac0-11cf-b6d1-00aa00bbbb58)
+]
+coclass JScriptAuthor {}
+
+[
+ helpstring("JScript Language Encoding"),
+ threading(both),
+ progid("JScript.Encode"),
+ uuid(f414c262-6ac0-11cf-b6d1-00aa00bbbb58)
+]
+coclass JScriptEncode {}
--- /dev/null
+HKCR
+{
+ NoRemove Interface
+ {
+ }
+ NoRemove CLSID
+ {
+ '{F414C260-6AC0-11CF-B6D1-00AA00BBBB58}' = s 'JScript Language'
+ {
+ InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both' }
+ ProgId = s 'JScript'
+ }
+ '{F414C261-6AC0-11CF-B6D1-00AA00BBBB58}' = s 'JScript Language Authoring'
+ {
+ InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both' }
+ ProgId = s 'JScript Author'
+ }
+ '{F414C262-6AC0-11CF-B6D1-00AA00BBBB58}' = s 'JScript Language Encoding'
+ {
+ InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both' }
+ ProgId = s 'JScript.Encode'
+ }
+ }
+ 'JScript' = s 'JScript Language'
+ {
+ CLSID = s '{F414C260-6AC0-11CF-B6D1-00AA00BBBB58}'
+ }
+ 'JScript Author' = s 'JScript Language Authoring'
+ {
+ CLSID = s '{F414C261-6AC0-11CF-B6D1-00AA00BBBB58}'
+ }
+ 'JScript.Encode' = s 'JScript Language Encoding'
+ {
+ CLSID = s '{F414C262-6AC0-11CF-B6D1-00AA00BBBB58}'
+ }
+}
#include <activaut.h>
#include <objsafe.h>
#include <mshtmhst.h>
+#include <rpcproxy.h>
+#include <jscript_classes.h>
#include <wine/debug.h>
LONG module_ref = 0;
-static const CLSID CLSID_JScript =
- {0xf414c260,0x6ac0,0x11cf,{0xb6,0xd1,0x00,0xaa,0x00,0xbb,0xbb,0x58}};
-static const CLSID CLSID_JScriptAuthor =
- {0xf414c261,0x6ac0,0x11cf,{0xb6,0xd1,0x00,0xaa,0x00,0xbb,0xbb,0x58}};
-static const CLSID CLSID_JScriptEncode =
- {0xf414c262,0x6ac0,0x11cf,{0xb6,0xd1,0x00,0xaa,0x00,0xbb,0xbb,0x58}};
-
DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
HINSTANCE jscript_hinstance;
return S_OK;
}
+static HRESULT WINAPI JScriptFactory_CreateInstance(IClassFactory *iface, IUnknown *outer,
+ REFIID riid, void **ppv)
+{
+ TRACE("(%p %s %p)\n", outer, debugstr_guid(riid), ppv);
+
+ if(outer) {
+ *ppv = NULL;
+ return CLASS_E_NOAGGREGATION;
+ }
+
+ return create_jscript_object(FALSE, riid, ppv);
+}
+
static const IClassFactoryVtbl JScriptFactoryVtbl = {
ClassFactory_QueryInterface,
ClassFactory_AddRef,
static IClassFactory JScriptFactory = { &JScriptFactoryVtbl };
+static HRESULT WINAPI JScriptEncodeFactory_CreateInstance(IClassFactory *iface, IUnknown *outer,
+ REFIID riid, void **ppv)
+{
+ TRACE("(%p %s %p)\n", outer, debugstr_guid(riid), ppv);
+
+ if(outer) {
+ *ppv = NULL;
+ return CLASS_E_NOAGGREGATION;
+ }
+
+ return create_jscript_object(TRUE, riid, ppv);
+}
+
+static const IClassFactoryVtbl JScriptEncodeFactoryVtbl = {
+ ClassFactory_QueryInterface,
+ ClassFactory_AddRef,
+ ClassFactory_Release,
+ JScriptEncodeFactory_CreateInstance,
+ ClassFactory_LockServer
+};
+
+static IClassFactory JScriptEncodeFactory = { &JScriptEncodeFactoryVtbl };
+
/******************************************************************
* DllMain (jscript.@)
*/
{
TRACE("(%p %d %p)\n", hInstDLL, fdwReason, lpv);
- switch(fdwReason)
- {
- case DLL_WINE_PREATTACH:
- return FALSE; /* prefer native version */
+ switch(fdwReason) {
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls(hInstDLL);
jscript_hinstance = hInstDLL;
+ if(!init_strings())
+ return FALSE;
break;
+ case DLL_PROCESS_DETACH:
+ free_strings();
}
return TRUE;
return IClassFactory_QueryInterface(&JScriptFactory, riid, ppv);
}
+ if(IsEqualGUID(&CLSID_JScriptEncode, rclsid)) {
+ TRACE("(CLSID_JScriptEncode %s %p)\n", debugstr_guid(riid), ppv);
+ return IClassFactory_QueryInterface(&JScriptEncodeFactory, riid, ppv);
+ }
+
FIXME("%s %s %p\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
return CLASS_E_CLASSNOTAVAILABLE;
}
return module_ref ? S_FALSE : S_OK;
}
-/***********************************************************************
- * register_inf
- */
-
-#define INF_SET_ID(id) \
- do \
- { \
- static CHAR name[] = #id; \
- \
- pse[i].pszName = name; \
- clsids[i++] = &id; \
- } while (0)
-
-static HRESULT register_inf(BOOL doregister)
-{
- HRESULT hres;
- HMODULE hAdvpack;
- HRESULT (WINAPI *pRegInstall)(HMODULE hm, LPCSTR pszSection, const STRTABLEA* pstTable);
- STRTABLEA strtable;
- STRENTRYA pse[7];
- static CLSID const *clsids[7];
- unsigned int i = 0;
-
- static const WCHAR advpackW[] = {'a','d','v','p','a','c','k','.','d','l','l',0};
-
- INF_SET_ID(CLSID_JScript);
- INF_SET_ID(CLSID_JScriptAuthor);
- INF_SET_ID(CLSID_JScriptEncode);
- INF_SET_ID(CATID_ActiveScript);
- INF_SET_ID(CATID_ActiveScriptParse);
- INF_SET_ID(CATID_ActiveScriptEncode);
- INF_SET_ID(CATID_ActiveScriptAuthor);
-
- for(i = 0; i < sizeof(pse)/sizeof(pse[0]); i++) {
- pse[i].pszValue = HeapAlloc(GetProcessHeap(), 0, 39);
- sprintf(pse[i].pszValue, "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
- clsids[i]->Data1, clsids[i]->Data2, clsids[i]->Data3, clsids[i]->Data4[0],
- clsids[i]->Data4[1], clsids[i]->Data4[2], clsids[i]->Data4[3], clsids[i]->Data4[4],
- clsids[i]->Data4[5], clsids[i]->Data4[6], clsids[i]->Data4[7]);
- }
-
- strtable.cEntries = sizeof(pse)/sizeof(pse[0]);
- strtable.pse = pse;
-
- hAdvpack = LoadLibraryW(advpackW);
- pRegInstall = (void *)GetProcAddress(hAdvpack, "RegInstall");
-
- hres = pRegInstall(jscript_hinstance, doregister ? "RegisterDll" : "UnregisterDll", &strtable);
-
- for(i=0; i < sizeof(pse)/sizeof(pse[0]); i++)
- HeapFree(GetProcessHeap(), 0, pse[i].pszValue);
-
- return hres;
-}
-
-#undef INF_SET_CLSID
-
/***********************************************************************
* DllRegisterServer (jscript.@)
*/
HRESULT WINAPI DllRegisterServer(void)
{
TRACE("()\n");
- return register_inf(TRUE);
+ return __wine_register_resources(jscript_hinstance);
}
/***********************************************************************
HRESULT WINAPI DllUnregisterServer(void)
{
TRACE("()\n");
- return register_inf(FALSE);
+ return __wine_unregister_resources(jscript_hinstance);
}
--- /dev/null
+/*
+ * Copyright 2008 Jacek Caban for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <math.h>
+
+#include "jscript.h"
+#include "regexp.h"
+
+#include <wine/debug.h>
+
+WINE_DEFAULT_DEBUG_CHANNEL(jscript);
+
+typedef struct {
+ jsdisp_t dispex;
+
+ regexp_t *jsregexp;
+ jsstr_t *str;
+ INT last_index;
+ jsval_t last_index_val;
+} RegExpInstance;
+
+static const WCHAR sourceW[] = {'s','o','u','r','c','e',0};
+static const WCHAR globalW[] = {'g','l','o','b','a','l',0};
+static const WCHAR ignoreCaseW[] = {'i','g','n','o','r','e','C','a','s','e',0};
+static const WCHAR multilineW[] = {'m','u','l','t','i','l','i','n','e',0};
+static const WCHAR lastIndexW[] = {'l','a','s','t','I','n','d','e','x',0};
+static const WCHAR toStringW[] = {'t','o','S','t','r','i','n','g',0};
+static const WCHAR execW[] = {'e','x','e','c',0};
+static const WCHAR testW[] = {'t','e','s','t',0};
+
+static const WCHAR leftContextW[] =
+ {'l','e','f','t','C','o','n','t','e','x','t',0};
+static const WCHAR rightContextW[] =
+ {'r','i','g','h','t','C','o','n','t','e','x','t',0};
+
+static const WCHAR idx1W[] = {'$','1',0};
+static const WCHAR idx2W[] = {'$','2',0};
+static const WCHAR idx3W[] = {'$','3',0};
+static const WCHAR idx4W[] = {'$','4',0};
+static const WCHAR idx5W[] = {'$','5',0};
+static const WCHAR idx6W[] = {'$','6',0};
+static const WCHAR idx7W[] = {'$','7',0};
+static const WCHAR idx8W[] = {'$','8',0};
+static const WCHAR idx9W[] = {'$','9',0};
+
+static const WCHAR emptyW[] = {0};
+
+static inline RegExpInstance *regexp_from_vdisp(vdisp_t *vdisp)
+{
+ return (RegExpInstance*)vdisp->u.jsdisp;
+}
+
+static void set_last_index(RegExpInstance *This, DWORD last_index)
+{
+ This->last_index = last_index;
+ jsval_release(This->last_index_val);
+ This->last_index_val = jsval_number(last_index);
+}
+
+static HRESULT do_regexp_match_next(script_ctx_t *ctx, RegExpInstance *regexp,
+ DWORD rem_flags, jsstr_t *str, match_state_t *ret)
+{
+ HRESULT hres;
+
+ hres = regexp_execute(regexp->jsregexp, ctx, &ctx->tmp_heap,
+ str->str, jsstr_length(str), ret);
+ if(FAILED(hres))
+ return hres;
+ if(hres == S_FALSE) {
+ if(rem_flags & REM_RESET_INDEX)
+ set_last_index(regexp, 0);
+ return S_FALSE;
+ }
+
+ if(!(rem_flags & REM_NO_CTX_UPDATE) && ctx->last_match != str) {
+ jsstr_release(ctx->last_match);
+ ctx->last_match = jsstr_addref(str);
+ }
+
+ if(!(rem_flags & REM_NO_CTX_UPDATE)) {
+ DWORD i, n = min(sizeof(ctx->match_parens)/sizeof(ctx->match_parens[0]), ret->paren_count);
+
+ for(i=0; i < n; i++) {
+ if(ret->parens[i].index == -1) {
+ ctx->match_parens[i].index = 0;
+ ctx->match_parens[i].length = 0;
+ }else {
+ ctx->match_parens[i].index = ret->parens[i].index;
+ ctx->match_parens[i].length = ret->parens[i].length;
+ }
+ }
+
+ if(n < sizeof(ctx->match_parens)/sizeof(ctx->match_parens[0]))
+ memset(ctx->match_parens+n, 0, sizeof(ctx->match_parens) - n*sizeof(ctx->match_parens[0]));
+ }
+
+ set_last_index(regexp, ret->cp-str->str);
+
+ if(!(rem_flags & REM_NO_CTX_UPDATE)) {
+ ctx->last_match_index = ret->cp-str->str-ret->match_len;
+ ctx->last_match_length = ret->match_len;
+ }
+
+ return S_OK;
+}
+
+HRESULT regexp_match_next(script_ctx_t *ctx, jsdisp_t *dispex,
+ DWORD rem_flags, jsstr_t *str, match_state_t **ret)
+{
+ RegExpInstance *regexp = (RegExpInstance*)dispex;
+ match_state_t *match;
+ heap_pool_t *mark;
+ HRESULT hres;
+
+ if((rem_flags & REM_CHECK_GLOBAL) && !(regexp->jsregexp->flags & REG_GLOB)) {
+ if(rem_flags & REM_ALLOC_RESULT)
+ *ret = NULL;
+ return S_FALSE;
+ }
+
+ if(rem_flags & REM_ALLOC_RESULT) {
+ match = alloc_match_state(regexp->jsregexp, NULL, str->str);
+ if(!match)
+ return E_OUTOFMEMORY;
+ *ret = match;
+ }
+
+ mark = heap_pool_mark(&ctx->tmp_heap);
+
+ if(rem_flags & REM_NO_PARENS) {
+ match = alloc_match_state(regexp->jsregexp, &ctx->tmp_heap, NULL);
+ if(!match) {
+ heap_pool_clear(mark);
+ return E_OUTOFMEMORY;
+ }
+ match->cp = (*ret)->cp;
+ match->match_len = (*ret)->match_len;
+ }else {
+ match = *ret;
+ }
+
+ hres = do_regexp_match_next(ctx, regexp, rem_flags, str, match);
+
+ if(rem_flags & REM_NO_PARENS) {
+ (*ret)->cp = match->cp;
+ (*ret)->match_len = match->match_len;
+ }
+
+ heap_pool_clear(mark);
+
+ if(hres != S_OK && (rem_flags & REM_ALLOC_RESULT)) {
+ heap_free(match);
+ *ret = NULL;
+ }
+
+ return hres;
+}
+
+static HRESULT regexp_match(script_ctx_t *ctx, jsdisp_t *dispex, jsstr_t *str, BOOL gflag,
+ match_result_t **match_result, DWORD *result_cnt)
+{
+ RegExpInstance *This = (RegExpInstance*)dispex;
+ match_result_t *ret = NULL;
+ match_state_t *result;
+ DWORD i=0, ret_size = 0;
+ heap_pool_t *mark;
+ HRESULT hres;
+
+ mark = heap_pool_mark(&ctx->tmp_heap);
+
+ result = alloc_match_state(This->jsregexp, &ctx->tmp_heap, str->str);
+ if(!result) {
+ heap_pool_clear(mark);
+ return E_OUTOFMEMORY;
+ }
+
+ while(1) {
+ hres = do_regexp_match_next(ctx, This, 0, str, result);
+ if(hres == S_FALSE) {
+ hres = S_OK;
+ break;
+ }
+
+ if(FAILED(hres))
+ break;
+
+ if(ret_size == i) {
+ if(ret) {
+ match_result_t *old_ret = ret;
+
+ ret = heap_realloc(old_ret, (ret_size <<= 1) * sizeof(match_result_t));
+ if(!ret)
+ heap_free(old_ret);
+ }else {
+ ret = heap_alloc((ret_size=4) * sizeof(match_result_t));
+ }
+ if(!ret) {
+ hres = E_OUTOFMEMORY;
+ break;
+ }
+ }
+
+ ret[i].index = result->cp - str->str - result->match_len;
+ ret[i++].length = result->match_len;
+
+ if(!gflag && !(This->jsregexp->flags & REG_GLOB)) {
+ hres = S_OK;
+ break;
+ }
+ }
+
+ heap_pool_clear(mark);
+ if(FAILED(hres)) {
+ heap_free(ret);
+ return hres;
+ }
+
+ *match_result = ret;
+ *result_cnt = i;
+ return S_OK;
+}
+
+static HRESULT RegExp_source(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
+{
+ TRACE("\n");
+
+ switch(flags) {
+ case DISPATCH_PROPERTYGET: {
+ RegExpInstance *This = regexp_from_vdisp(jsthis);
+ *r = jsval_string(jsstr_addref(This->str));
+ break;
+ }
+ default:
+ FIXME("Unimplemented flags %x\n", flags);
+ return E_NOTIMPL;
+ }
+
+ return S_OK;
+}
+
+static HRESULT RegExp_global(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT RegExp_ignoreCase(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT RegExp_multiline(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static INT index_from_val(script_ctx_t *ctx, jsval_t v)
+{
+ double n;
+ HRESULT hres;
+
+ hres = to_number(ctx, v, &n);
+ if(FAILED(hres)) {
+ clear_ei(ctx); /* FIXME: Move ignoring exceptions to to_primitive */
+ return 0;
+ }
+
+ n = floor(n);
+ return is_int32(n) ? n : 0;
+}
+
+static HRESULT RegExp_lastIndex(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
+{
+ TRACE("\n");
+
+ switch(flags) {
+ case DISPATCH_PROPERTYGET: {
+ RegExpInstance *regexp = regexp_from_vdisp(jsthis);
+
+ return jsval_copy(regexp->last_index_val, r);
+ }
+ case DISPATCH_PROPERTYPUT: {
+ RegExpInstance *regexp = regexp_from_vdisp(jsthis);
+ HRESULT hres;
+
+ hres = jsval_copy(argv[0], ®exp->last_index_val);
+ if(FAILED(hres))
+ return hres;
+
+ regexp->last_index = index_from_val(ctx, argv[0]);
+ break;
+ }
+ default:
+ FIXME("unimplemented flags: %x\n", flags);
+ return E_NOTIMPL;
+ }
+
+ return S_OK;
+}
+
+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;
+}
+
+static HRESULT create_match_array(script_ctx_t *ctx, jsstr_t *input,
+ const match_state_t *result, IDispatch **ret)
+{
+ jsdisp_t *array;
+ jsstr_t *str;
+ DWORD i;
+ HRESULT hres = S_OK;
+
+ static const WCHAR indexW[] = {'i','n','d','e','x',0};
+ static const WCHAR inputW[] = {'i','n','p','u','t',0};
+ static const WCHAR lastIndexW[] = {'l','a','s','t','I','n','d','e','x',0};
+ static const WCHAR zeroW[] = {'0',0};
+
+ 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);
+ else
+ str = jsstr_empty();
+ if(!str) {
+ hres = E_OUTOFMEMORY;
+ break;
+ }
+
+ hres = jsdisp_propput_idx(array, i+1, jsval_string(str));
+ jsstr_release(str);
+ if(FAILED(hres))
+ break;
+ }
+
+ while(SUCCEEDED(hres)) {
+ hres = jsdisp_propput_name(array, indexW, jsval_number(result->cp-input->str-result->match_len));
+ if(FAILED(hres))
+ break;
+
+ hres = jsdisp_propput_name(array, lastIndexW, jsval_number(result->cp-input->str));
+ if(FAILED(hres))
+ break;
+
+ hres = jsdisp_propput_name(array, inputW, jsval_string(jsstr_addref(input)));
+ if(FAILED(hres))
+ break;
+
+ str = jsstr_alloc_len(result->cp-result->match_len, result->match_len);
+ if(!str) {
+ hres = E_OUTOFMEMORY;
+ break;
+ }
+ hres = jsdisp_propput_name(array, zeroW, jsval_string(str));
+ jsstr_release(str);
+ break;
+ }
+
+ if(FAILED(hres)) {
+ jsdisp_release(array);
+ return hres;
+ }
+
+ *ret = to_disp(array);
+ return S_OK;
+}
+
+static HRESULT run_exec(script_ctx_t *ctx, vdisp_t *jsthis, jsval_t arg,
+ jsstr_t **input, match_state_t **result, BOOL *ret)
+{
+ RegExpInstance *regexp;
+ match_state_t *match;
+ DWORD last_index = 0;
+ jsstr_t *string;
+ HRESULT hres;
+
+ if(!is_vclass(jsthis, JSCLASS_REGEXP)) {
+ FIXME("Not a RegExp\n");
+ return E_NOTIMPL;
+ }
+
+ regexp = regexp_from_vdisp(jsthis);
+
+ hres = to_string(ctx, arg, &string);
+ if(FAILED(hres))
+ return hres;
+
+ if(regexp->jsregexp->flags & REG_GLOB) {
+ if(regexp->last_index < 0) {
+ jsstr_release(string);
+ set_last_index(regexp, 0);
+ *ret = FALSE;
+ if(input)
+ *input = jsstr_empty();
+ return S_OK;
+ }
+
+ last_index = regexp->last_index;
+ }
+
+ match = alloc_match_state(regexp->jsregexp, &ctx->tmp_heap, string->str+last_index);
+ if(!match) {
+ jsstr_release(string);
+ return E_OUTOFMEMORY;
+ }
+
+ hres = regexp_match_next(ctx, ®exp->dispex, REM_RESET_INDEX, string, &match);
+ if(FAILED(hres)) {
+ jsstr_release(string);
+ return hres;
+ }
+
+ *result = match;
+ *ret = hres == S_OK;
+ if(input)
+ *input = string;
+ else
+ jsstr_release(string);
+ return S_OK;
+}
+
+static HRESULT RegExp_exec(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
+{
+ match_state_t *match;
+ heap_pool_t *mark;
+ BOOL b;
+ jsstr_t *string;
+ HRESULT hres;
+
+ TRACE("\n");
+
+ mark = heap_pool_mark(&ctx->tmp_heap);
+
+ hres = run_exec(ctx, jsthis, argc ? argv[0] : jsval_string(jsstr_empty()), &string, &match, &b);
+ if(FAILED(hres)) {
+ heap_pool_clear(mark);
+ return hres;
+ }
+
+ if(r) {
+ if(b) {
+ IDispatch *ret;
+
+ hres = create_match_array(ctx, string, match, &ret);
+ if(SUCCEEDED(hres))
+ *r = jsval_disp(ret);
+ }else {
+ *r = jsval_null();
+ }
+ }
+
+ heap_pool_clear(mark);
+ jsstr_release(string);
+ return hres;
+}
+
+static HRESULT RegExp_test(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
+{
+ match_state_t *match;
+ jsstr_t *undef_str;
+ heap_pool_t *mark;
+ BOOL b;
+ HRESULT hres;
+
+ TRACE("\n");
+
+ mark = heap_pool_mark(&ctx->tmp_heap);
+ hres = run_exec(ctx, jsthis, argc ? argv[0] : jsval_string(undef_str = jsstr_undefined()), NULL, &match, &b);
+ heap_pool_clear(mark);
+ if(!argc)
+ jsstr_release(undef_str);
+ if(FAILED(hres))
+ return hres;
+
+ if(r)
+ *r = jsval_bool(b);
+ return S_OK;
+}
+
+static HRESULT RegExp_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
+{
+ TRACE("\n");
+
+ switch(flags) {
+ case INVOKE_FUNC:
+ return throw_type_error(ctx, JS_E_FUNCTION_EXPECTED, NULL);
+ default:
+ FIXME("unimplemented flags %x\n", flags);
+ return E_NOTIMPL;
+ }
+
+ return S_OK;
+}
+
+static void RegExp_destructor(jsdisp_t *dispex)
+{
+ RegExpInstance *This = (RegExpInstance*)dispex;
+
+ if(This->jsregexp)
+ regexp_destroy(This->jsregexp);
+ jsval_release(This->last_index_val);
+ jsstr_release(This->str);
+ heap_free(This);
+}
+
+static const builtin_prop_t RegExp_props[] = {
+ {execW, RegExp_exec, PROPF_METHOD|1},
+ {globalW, RegExp_global, 0},
+ {ignoreCaseW, RegExp_ignoreCase, 0},
+ {lastIndexW, RegExp_lastIndex, 0},
+ {multilineW, RegExp_multiline, 0},
+ {sourceW, RegExp_source, 0},
+ {testW, RegExp_test, PROPF_METHOD|1},
+ {toStringW, RegExp_toString, PROPF_METHOD}
+};
+
+static const builtin_info_t RegExp_info = {
+ JSCLASS_REGEXP,
+ {NULL, RegExp_value, 0},
+ sizeof(RegExp_props)/sizeof(*RegExp_props),
+ RegExp_props,
+ RegExp_destructor,
+ NULL
+};
+
+static const builtin_prop_t RegExpInst_props[] = {
+ {globalW, RegExp_global, 0},
+ {ignoreCaseW, RegExp_ignoreCase, 0},
+ {lastIndexW, RegExp_lastIndex, 0},
+ {multilineW, RegExp_multiline, 0},
+ {sourceW, RegExp_source, 0}
+};
+
+static const builtin_info_t RegExpInst_info = {
+ JSCLASS_REGEXP,
+ {NULL, RegExp_value, 0},
+ sizeof(RegExpInst_props)/sizeof(*RegExpInst_props),
+ RegExpInst_props,
+ RegExp_destructor,
+ NULL
+};
+
+static HRESULT alloc_regexp(script_ctx_t *ctx, jsdisp_t *object_prototype, RegExpInstance **ret)
+{
+ RegExpInstance *regexp;
+ HRESULT hres;
+
+ regexp = heap_alloc_zero(sizeof(RegExpInstance));
+ if(!regexp)
+ return E_OUTOFMEMORY;
+
+ if(object_prototype)
+ hres = init_dispex(®exp->dispex, ctx, &RegExp_info, object_prototype);
+ else
+ hres = init_dispex_from_constr(®exp->dispex, ctx, &RegExpInst_info, ctx->regexp_constr);
+
+ if(FAILED(hres)) {
+ heap_free(regexp);
+ return hres;
+ }
+
+ *ret = regexp;
+ return S_OK;
+}
+
+HRESULT create_regexp(script_ctx_t *ctx, jsstr_t *src, DWORD flags, jsdisp_t **ret)
+{
+ RegExpInstance *regexp;
+ HRESULT hres;
+
+ TRACE("%s %x\n", debugstr_jsstr(src), flags);
+
+ hres = alloc_regexp(ctx, NULL, ®exp);
+ if(FAILED(hres))
+ return hres;
+
+ regexp->str = jsstr_addref(src);
+ regexp->last_index_val = jsval_number(0);
+
+ regexp->jsregexp = regexp_new(ctx, &ctx->tmp_heap, regexp->str->str,
+ jsstr_length(regexp->str), flags, FALSE);
+ if(FAILED(hres)) {
+ WARN("regexp_new failed\n");
+ jsdisp_release(®exp->dispex);
+ return E_FAIL;
+ }
+
+ *ret = ®exp->dispex;
+ return S_OK;
+}
+
+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;
+ HRESULT hres;
+
+ if(is_object_instance(src_arg)) {
+ jsdisp_t *obj;
+
+ obj = iface_to_jsdisp((IUnknown*)get_object(src_arg));
+ if(obj) {
+ if(is_class(obj, JSCLASS_REGEXP)) {
+ RegExpInstance *regexp = (RegExpInstance*)obj;
+
+ hres = create_regexp(ctx, regexp->str, regexp->jsregexp->flags, ret);
+ jsdisp_release(obj);
+ return hres;
+ }
+
+ jsdisp_release(obj);
+ }
+ }
+
+ if(!is_string(src_arg)) {
+ FIXME("src_arg = %s\n", debugstr_jsval(src_arg));
+ return E_NOTIMPL;
+ }
+
+ src = get_string(src_arg);
+
+ if(flags_arg) {
+ if(!is_string(*flags_arg)) {
+ FIXME("unimplemented for %s\n", debugstr_jsval(*flags_arg));
+ return E_NOTIMPL;
+ }
+
+ opt = get_string(*flags_arg);
+ }
+
+ hres = parse_regexp_flags(opt ? opt->str : NULL, opt ? jsstr_length(opt) : 0, &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)
+{
+ static const WCHAR indexW[] = {'i','n','d','e','x',0};
+ static const WCHAR inputW[] = {'i','n','p','u','t',0};
+ static const WCHAR lastIndexW[] = {'l','a','s','t','I','n','d','e','x',0};
+
+ RegExpInstance *regexp = (RegExpInstance*)re;
+ match_result_t *match_result;
+ unsigned match_cnt, i;
+ jsdisp_t *array;
+ HRESULT hres;
+
+ 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);
+ if(!match) {
+ heap_pool_clear(mark);
+ return E_OUTOFMEMORY;
+ }
+
+ hres = regexp_match_next(ctx, ®exp->dispex, 0, str, &match);
+ if(FAILED(hres)) {
+ heap_pool_clear(mark);
+ return hres;
+ }
+
+ if(r) {
+ if(hres == S_OK) {
+ IDispatch *ret;
+
+ hres = create_match_array(ctx, str, match, &ret);
+ if(SUCCEEDED(hres))
+ *r = jsval_disp(ret);
+ }else {
+ *r = jsval_null();
+ }
+ }
+
+ heap_pool_clear(mark);
+ return S_OK;
+ }
+
+ hres = regexp_match(ctx, ®exp->dispex, str, FALSE, &match_result, &match_cnt);
+ if(FAILED(hres))
+ return hres;
+
+ if(!match_cnt) {
+ TRACE("no match\n");
+
+ if(r)
+ *r = jsval_null();
+ return S_OK;
+ }
+
+ hres = create_array(ctx, match_cnt, &array);
+ if(FAILED(hres))
+ return hres;
+
+ for(i=0; i < match_cnt; i++) {
+ jsstr_t *tmp_str;
+
+ tmp_str = jsstr_substr(str, match_result[i].index, match_result[i].length);
+ if(!tmp_str) {
+ hres = E_OUTOFMEMORY;
+ break;
+ }
+
+ hres = jsdisp_propput_idx(array, i, jsval_string(tmp_str));
+ jsstr_release(tmp_str);
+ if(FAILED(hres))
+ break;
+ }
+
+ while(SUCCEEDED(hres)) {
+ hres = jsdisp_propput_name(array, indexW, jsval_number(match_result[match_cnt-1].index));
+ if(FAILED(hres))
+ break;
+
+ hres = jsdisp_propput_name(array, lastIndexW,
+ jsval_number(match_result[match_cnt-1].index + match_result[match_cnt-1].length));
+ if(FAILED(hres))
+ break;
+
+ hres = jsdisp_propput_name(array, inputW, jsval_string(str));
+ break;
+ }
+
+ heap_free(match_result);
+
+ if(SUCCEEDED(hres) && r)
+ *r = jsval_obj(array);
+ else
+ jsdisp_release(array);
+ return hres;
+}
+
+static HRESULT global_idx(script_ctx_t *ctx, DWORD flags, DWORD idx, jsval_t *r)
+{
+ switch(flags) {
+ case DISPATCH_PROPERTYGET: {
+ jsstr_t *ret;
+
+ ret = jsstr_substr(ctx->last_match, ctx->match_parens[idx].index, ctx->match_parens[idx].length);
+ if(!ret)
+ return E_OUTOFMEMORY;
+
+ *r = jsval_string(ret);
+ break;
+ }
+ case DISPATCH_PROPERTYPUT:
+ break;
+ default:
+ FIXME("unsupported flags\n");
+ return E_NOTIMPL;
+ }
+
+ return S_OK;
+}
+
+static HRESULT RegExpConstr_idx1(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
+ unsigned argc, jsval_t *argv, jsval_t *r)
+{
+ TRACE("\n");
+ return global_idx(ctx, flags, 0, r);
+}
+
+static HRESULT RegExpConstr_idx2(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
+ unsigned argc, jsval_t *argv, jsval_t *r)
+{
+ TRACE("\n");
+ return global_idx(ctx, flags, 1, r);
+}
+
+static HRESULT RegExpConstr_idx3(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
+ unsigned argc, jsval_t *argv, jsval_t *r)
+{
+ TRACE("\n");
+ return global_idx(ctx, flags, 2, r);
+}
+
+static HRESULT RegExpConstr_idx4(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
+ unsigned argc, jsval_t *argv, jsval_t *r)
+{
+ TRACE("\n");
+ return global_idx(ctx, flags, 3, r);
+}
+
+static HRESULT RegExpConstr_idx5(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
+ unsigned argc, jsval_t *argv, jsval_t *r)
+{
+ TRACE("\n");
+ return global_idx(ctx, flags, 4, r);
+}
+
+static HRESULT RegExpConstr_idx6(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
+ unsigned argc, jsval_t *argv, jsval_t *r)
+{
+ TRACE("\n");
+ return global_idx(ctx, flags, 5, r);
+}
+
+static HRESULT RegExpConstr_idx7(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
+ unsigned argc, jsval_t *argv, jsval_t *r)
+{
+ TRACE("\n");
+ return global_idx(ctx, flags, 6, r);
+}
+
+static HRESULT RegExpConstr_idx8(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
+ unsigned argc, jsval_t *argv, jsval_t *r)
+{
+ TRACE("\n");
+ return global_idx(ctx, flags, 7, r);
+}
+
+static HRESULT RegExpConstr_idx9(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
+ unsigned argc, jsval_t *argv, jsval_t *r)
+{
+ TRACE("\n");
+ return global_idx(ctx, flags, 8, r);
+}
+
+static HRESULT RegExpConstr_leftContext(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
+ unsigned argc, jsval_t *argv, jsval_t *r)
+{
+ TRACE("\n");
+
+ switch(flags) {
+ case DISPATCH_PROPERTYGET: {
+ jsstr_t *ret;
+
+ ret = jsstr_substr(ctx->last_match, 0, ctx->last_match_index);
+ if(!ret)
+ return E_OUTOFMEMORY;
+
+ *r = jsval_string(ret);
+ break;
+ }
+ case DISPATCH_PROPERTYPUT:
+ break;
+ default:
+ FIXME("unsupported flags\n");
+ return E_NOTIMPL;
+ }
+
+ return S_OK;
+}
+
+static HRESULT RegExpConstr_rightContext(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
+ unsigned argc, jsval_t *argv, jsval_t *r)
+{
+ TRACE("\n");
+
+ switch(flags) {
+ case DISPATCH_PROPERTYGET: {
+ jsstr_t *ret;
+
+ ret = jsstr_substr(ctx->last_match, ctx->last_match_index+ctx->last_match_length,
+ jsstr_length(ctx->last_match) - ctx->last_match_index - ctx->last_match_length);
+ if(!ret)
+ return E_OUTOFMEMORY;
+
+ *r = jsval_string(ret);
+ break;
+ }
+ case DISPATCH_PROPERTYPUT:
+ break;
+ default:
+ FIXME("unsupported flags\n");
+ return E_NOTIMPL;
+ }
+
+ return S_OK;
+}
+
+static HRESULT RegExpConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
+{
+ TRACE("\n");
+
+ switch(flags) {
+ case DISPATCH_METHOD:
+ if(argc) {
+ if(is_object_instance(argv[0])) {
+ jsdisp_t *jsdisp = iface_to_jsdisp((IUnknown*)get_object(argv[0]));
+ if(jsdisp) {
+ if(is_class(jsdisp, JSCLASS_REGEXP)) {
+ if(argc > 1 && !is_undefined(argv[1])) {
+ jsdisp_release(jsdisp);
+ return throw_regexp_error(ctx, JS_E_REGEXP_SYNTAX, NULL);
+ }
+
+ if(r)
+ *r = jsval_obj(jsdisp);
+ else
+ jsdisp_release(jsdisp);
+ return S_OK;
+ }
+ jsdisp_release(jsdisp);
+ }
+ }
+ }
+ /* fall through */
+ case DISPATCH_CONSTRUCT: {
+ jsdisp_t *ret;
+ HRESULT hres;
+
+ if(!argc) {
+ FIXME("no args\n");
+ return E_NOTIMPL;
+ }
+
+ hres = create_regexp_var(ctx, argv[0], argc > 1 ? argv+1 : NULL, &ret);
+ if(FAILED(hres))
+ return hres;
+
+ if(r)
+ *r = jsval_obj(ret);
+ else
+ jsdisp_release(ret);
+ return S_OK;
+ }
+ default:
+ FIXME("unimplemented flags: %x\n", flags);
+ return E_NOTIMPL;
+ }
+
+ return S_OK;
+}
+
+static const builtin_prop_t RegExpConstr_props[] = {
+ {idx1W, RegExpConstr_idx1, 0},
+ {idx2W, RegExpConstr_idx2, 0},
+ {idx3W, RegExpConstr_idx3, 0},
+ {idx4W, RegExpConstr_idx4, 0},
+ {idx5W, RegExpConstr_idx5, 0},
+ {idx6W, RegExpConstr_idx6, 0},
+ {idx7W, RegExpConstr_idx7, 0},
+ {idx8W, RegExpConstr_idx8, 0},
+ {idx9W, RegExpConstr_idx9, 0},
+ {leftContextW, RegExpConstr_leftContext, 0},
+ {rightContextW, RegExpConstr_rightContext, 0}
+};
+
+static const builtin_info_t RegExpConstr_info = {
+ JSCLASS_FUNCTION,
+ {NULL, Function_value, 0},
+ sizeof(RegExpConstr_props)/sizeof(*RegExpConstr_props),
+ RegExpConstr_props,
+ NULL,
+ NULL
+};
+
+HRESULT create_regexp_constr(script_ctx_t *ctx, jsdisp_t *object_prototype, jsdisp_t **ret)
+{
+ RegExpInstance *regexp;
+ HRESULT hres;
+
+ static const WCHAR RegExpW[] = {'R','e','g','E','x','p',0};
+
+ hres = alloc_regexp(ctx, object_prototype, ®exp);
+ if(FAILED(hres))
+ return hres;
+
+ hres = create_builtin_constructor(ctx, RegExpConstr_value, RegExpW, &RegExpConstr_info,
+ PROPF_CONSTR|2, ®exp->dispex, ret);
+
+ jsdisp_release(®exp->dispex);
+ return hres;
+}
+
+HRESULT parse_regexp_flags(const WCHAR *str, DWORD str_len, DWORD *ret)
+{
+ const WCHAR *p;
+ DWORD flags = 0;
+
+ for (p = str; p < str+str_len; p++) {
+ switch (*p) {
+ case 'g':
+ flags |= REG_GLOB;
+ break;
+ case 'i':
+ flags |= REG_FOLD;
+ break;
+ case 'm':
+ flags |= REG_MULTILINE;
+ break;
+ case 'y':
+ flags |= REG_STICKY;
+ break;
+ default:
+ WARN("wrong flag %c\n", *p);
+ return E_FAIL;
+ }
+ }
+
+ *ret = flags;
+ return S_OK;
+}
--- /dev/null
+/*
+ * Copyright 2012 Jacek Caban for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "jscript.h"
+
+#include <wine/debug.h>
+
+const char *debugstr_jsstr(jsstr_t *str)
+{
+ return debugstr_wn(str->str, jsstr_length(str));
+}
+
+jsstr_t *jsstr_alloc_buf(unsigned len)
+{
+ jsstr_t *ret;
+
+ if(len > JSSTR_MAX_LENGTH)
+ return NULL;
+
+ ret = heap_alloc(FIELD_OFFSET(jsstr_t, str[len+1]));
+ if(!ret)
+ return NULL;
+
+ ret->length_flags = len << JSSTR_LENGTH_SHIFT;
+ ret->ref = 1;
+ ret->str[len] = 0;
+ return ret;
+}
+
+jsstr_t *jsstr_alloc_len(const WCHAR *buf, unsigned len)
+{
+ jsstr_t *ret;
+
+ ret = jsstr_alloc_buf(len);
+ if(ret)
+ memcpy(ret->str, buf, len*sizeof(WCHAR));
+
+ return ret;
+}
+
+int jsstr_cmp(jsstr_t *str1, jsstr_t *str2)
+{
+ int len1 = jsstr_length(str1);
+ int len2 = jsstr_length(str2);
+ int ret;
+
+ ret = memcmp(str1->str, str2->str, min(len1, len2)*sizeof(WCHAR));
+ if(!ret)
+ ret = len1 - len2;
+
+ return ret;
+}
+
+jsstr_t *jsstr_concat(jsstr_t *str1, jsstr_t *str2)
+{
+ unsigned len1, len2;
+ jsstr_t *ret;
+
+ len1 = jsstr_length(str1);
+ if(!len1)
+ return jsstr_addref(str2);
+
+ len2 = jsstr_length(str2);
+ if(!len2)
+ return jsstr_addref(str1);
+
+ ret = jsstr_alloc_buf(len1+len2);
+ if(!ret)
+ return NULL;
+
+ jsstr_flush(str1, ret->str);
+ jsstr_flush(str2, ret->str+len1);
+ return ret;
+}
+
+static jsstr_t *empty_str, *nan_str, *undefined_str;
+
+jsstr_t *jsstr_nan(void)
+{
+ return jsstr_addref(nan_str);
+}
+
+jsstr_t *jsstr_empty(void)
+{
+ return jsstr_addref(empty_str);
+}
+
+jsstr_t *jsstr_undefined(void)
+{
+ return jsstr_addref(undefined_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)))
+ return FALSE;
+ if(!(nan_str = jsstr_alloc(NaNW)))
+ return FALSE;
+ if(!(undefined_str = jsstr_alloc(undefinedW)))
+ return FALSE;
+ return TRUE;
+}
+
+void free_strings(void)
+{
+ jsstr_release(empty_str);
+ jsstr_release(nan_str);
+ jsstr_release(undefined_str);
+}
--- /dev/null
+/*
+ * Copyright 2012 Jacek Caban for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+struct _jsstr_t {
+ unsigned length_flags;
+ unsigned ref;
+ WCHAR str[1];
+};
+
+#define JSSTR_LENGTH_SHIFT 4
+#define JSSTR_MAX_LENGTH (1 << (32-JSSTR_LENGTH_SHIFT))
+#define JSSTR_FLAGS_MASK ((1 << JSSTR_LENGTH_SHIFT)-1)
+
+#define JSSTR_FLAG_NULLBSTR 1
+
+static inline unsigned jsstr_length(jsstr_t *str)
+{
+ return str->length_flags >> JSSTR_LENGTH_SHIFT;
+}
+
+jsstr_t *jsstr_alloc_len(const WCHAR*,unsigned) DECLSPEC_HIDDEN;
+jsstr_t *jsstr_alloc_buf(unsigned) DECLSPEC_HIDDEN;
+
+static inline jsstr_t *jsstr_alloc(const WCHAR *str)
+{
+ return jsstr_alloc_len(str, strlenW(str));
+}
+
+static inline void jsstr_release(jsstr_t *str)
+{
+ if(!--str->ref)
+ heap_free(str);
+}
+
+static inline jsstr_t *jsstr_addref(jsstr_t *str)
+{
+ str->ref++;
+ return str;
+}
+
+static inline BOOL jsstr_eq(jsstr_t *str1, jsstr_t *str2)
+{
+ unsigned len = jsstr_length(str1);
+ return len == jsstr_length(str2) && !memcmp(str1->str, str2->str, len*sizeof(WCHAR));
+}
+
+static inline unsigned jsstr_flush(jsstr_t *str, WCHAR *buf)
+{
+ unsigned len = jsstr_length(str);
+ memcpy(buf, str->str, len*sizeof(WCHAR));
+ return len;
+}
+
+static inline jsstr_t *jsstr_substr(jsstr_t *str, unsigned off, unsigned len)
+{
+ return jsstr_alloc_len(str->str+off, len);
+}
+
+int jsstr_cmp(jsstr_t*,jsstr_t*) DECLSPEC_HIDDEN;
+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;
+
+BOOL init_strings(void) DECLSPEC_HIDDEN;
+void free_strings(void) DECLSPEC_HIDDEN;
+
+const char *debugstr_jsstr(jsstr_t*) DECLSPEC_HIDDEN;
#include <wine/port.h>
//#include <math.h>
+#include <assert.h>
#include "jscript.h"
//#include "engine.h"
return "{VT_NULL}";
case VT_I4:
return wine_dbg_sprintf("{VT_I4: %d}", V_I4(v));
+ case VT_UI4:
+ return wine_dbg_sprintf("{VT_UI4: %u}", V_UI4(v));
case VT_R8:
return wine_dbg_sprintf("{VT_R8: %lf}", V_R8(v));
case VT_BSTR:
return wine_dbg_sprintf("{VT_DISPATCH: %p}", V_DISPATCH(v));
case VT_BOOL:
return wine_dbg_sprintf("{VT_BOOL: %x}", V_BOOL(v));
+ case VT_ARRAY|VT_VARIANT:
+ return "{VT_ARRAY|VT_VARIANT: ...}";
default:
return wine_dbg_sprintf("{vt %d}", V_VT(v));
}
}
+const char *debugstr_jsval(const jsval_t v)
+{
+ switch(jsval_type(v)) {
+ case JSV_UNDEFINED:
+ return "undefined";
+ case JSV_NULL:
+ return "null";
+ case JSV_OBJECT:
+ return wine_dbg_sprintf("obj(%p)", get_object(v));
+ case JSV_STRING:
+ return wine_dbg_sprintf("str(%s)", debugstr_jsstr(get_string(v)));
+ case JSV_NUMBER:
+ return wine_dbg_sprintf("%lf", get_number(v));
+ case JSV_BOOL:
+ return get_bool(v) ? "true" : "false";
+ case JSV_VARIANT:
+ return debugstr_variant(get_variant(v));
+ }
+
+ assert(0);
+ return NULL;
+}
+
#define MIN_BLOCK_SIZE 128
#define ARENA_FREE_FILLER 0xaa
return MIN_BLOCK_SIZE << block;
}
-void jsheap_init(jsheap_t *heap)
+void heap_pool_init(heap_pool_t *heap)
{
memset(heap, 0, sizeof(*heap));
list_init(&heap->custom_blocks);
}
-void *jsheap_alloc(jsheap_t *heap, DWORD size)
+void *heap_pool_alloc(heap_pool_t *heap, DWORD size)
{
struct list *list;
void *tmp;
return list+1;
}
-void *jsheap_grow(jsheap_t *heap, void *mem, DWORD size, DWORD inc)
+void *heap_pool_grow(heap_pool_t *heap, void *mem, DWORD size, DWORD inc)
{
+ void *ret;
+
if(mem == (BYTE*)heap->blocks[heap->last_block] + heap->offset-size
&& heap->offset+inc < block_size(heap->last_block)) {
heap->offset += inc;
return mem;
}
- return jsheap_alloc(heap, size+inc);
+ ret = heap_pool_alloc(heap, size+inc);
+ if(ret) /* FIXME: avoid copying for custom blocks */
+ memcpy(ret, mem, size);
+ return ret;
}
-void jsheap_clear(jsheap_t *heap)
+void heap_pool_clear(heap_pool_t *heap)
{
struct list *tmp;
heap->mark = FALSE;
}
-void jsheap_free(jsheap_t *heap)
+void heap_pool_free(heap_pool_t *heap)
{
DWORD i;
- jsheap_clear(heap);
+ heap_pool_clear(heap);
for(i=0; i < heap->block_cnt; i++)
heap_free(heap->blocks[i]);
heap_free(heap->blocks);
- jsheap_init(heap);
+ heap_pool_init(heap);
}
-jsheap_t *jsheap_mark(jsheap_t *heap)
+heap_pool_t *heap_pool_mark(heap_pool_t *heap)
{
if(heap->mark)
return NULL;
return heap;
}
-/* ECMA-262 3rd Edition 9.1 */
-HRESULT to_primitive(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, VARIANT *ret, hint_t hint)
+void jsval_release(jsval_t val)
{
- switch(V_VT(v)) {
+ switch(jsval_type(val)) {
+ case JSV_OBJECT:
+ if(get_object(val))
+ IDispatch_Release(get_object(val));
+ break;
+ case JSV_STRING:
+ jsstr_release(get_string(val));
+ break;
+ case JSV_VARIANT:
+ VariantClear(get_variant(val));
+ heap_free(get_variant(val));
+ break;
+ default:
+ break;
+ }
+}
+
+static HRESULT jsval_variant(jsval_t *val, VARIANT *var)
+{
+ VARIANT *v;
+ HRESULT hres;
+
+ __JSVAL_TYPE(*val) = JSV_VARIANT;
+ __JSVAL_VAR(*val) = v = heap_alloc(sizeof(VARIANT));
+ if(!v)
+ return E_OUTOFMEMORY;
+
+ V_VT(v) = VT_EMPTY;
+ hres = VariantCopy(v, var);
+ if(FAILED(hres))
+ heap_free(v);
+ return hres;
+}
+
+HRESULT jsval_copy(jsval_t v, jsval_t *r)
+{
+ switch(jsval_type(v)) {
+ case JSV_UNDEFINED:
+ case JSV_NULL:
+ case JSV_NUMBER:
+ case JSV_BOOL:
+ *r = v;
+ return S_OK;
+ case JSV_OBJECT:
+ if(get_object(v))
+ IDispatch_AddRef(get_object(v));
+ *r = v;
+ return S_OK;
+ case JSV_STRING: {
+ jsstr_addref(get_string(v));
+ *r = v;
+ return S_OK;
+ }
+ case JSV_VARIANT:
+ return jsval_variant(r, get_variant(v));
+ }
+
+ assert(0);
+ return E_FAIL;
+}
+
+HRESULT variant_to_jsval(VARIANT *var, jsval_t *r)
+{
+ switch(V_VT(var)) {
case VT_EMPTY:
+ *r = jsval_undefined();
+ return S_OK;
case VT_NULL:
+ *r = jsval_null();
+ return S_OK;
case VT_BOOL:
+ *r = jsval_bool(V_BOOL(var));
+ return S_OK;
case VT_I4:
+ *r = jsval_number(V_I4(var));
+ return S_OK;
case VT_R8:
- *ret = *v;
- break;
- case VT_BSTR:
- V_VT(ret) = VT_BSTR;
- V_BSTR(ret) = SysAllocString(V_BSTR(v));
- break;
+ *r = jsval_number(V_R8(var));
+ return S_OK;
+ 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;
+
+ *r = jsval_string(str);
+ return S_OK;
+ }
case VT_DISPATCH: {
- DispatchEx *jsdisp;
+ if(V_DISPATCH(var))
+ IDispatch_AddRef(V_DISPATCH(var));
+ *r = jsval_disp(V_DISPATCH(var));
+ return S_OK;
+ }
+ case VT_I2:
+ *r = jsval_number(V_I2(var));
+ return S_OK;
+ case VT_INT:
+ *r = jsval_number(V_INT(var));
+ return S_OK;
+ case VT_UNKNOWN:
+ if(V_UNKNOWN(var)) {
+ IDispatch *disp;
+ HRESULT hres;
+
+ hres = IUnknown_QueryInterface(V_UNKNOWN(var), &IID_IDispatch, (void**)&disp);
+ if(SUCCEEDED(hres)) {
+ *r = jsval_disp(disp);
+ return S_OK;
+ }
+ }
+ /* fall through */
+ default:
+ return jsval_variant(r, var);
+ }
+}
+
+HRESULT jsval_to_variant(jsval_t val, VARIANT *retv)
+{
+ switch(jsval_type(val)) {
+ case JSV_UNDEFINED:
+ V_VT(retv) = VT_EMPTY;
+ return S_OK;
+ case JSV_NULL:
+ V_VT(retv) = VT_NULL;
+ return S_OK;
+ case JSV_OBJECT:
+ V_VT(retv) = VT_DISPATCH;
+ if(get_object(val))
+ IDispatch_AddRef(get_object(val));
+ V_DISPATCH(retv) = get_object(val);
+ return S_OK;
+ case JSV_STRING: {
+ jsstr_t *str = get_string(val);
+
+ V_VT(retv) = VT_BSTR;
+ if(str->length_flags & JSSTR_FLAG_NULLBSTR) {
+ V_BSTR(retv) = NULL;
+ }else {
+ V_BSTR(retv) = SysAllocStringLen(NULL, jsstr_length(str));
+ if(V_BSTR(retv))
+ jsstr_flush(str, V_BSTR(retv));
+ else
+ return E_OUTOFMEMORY;
+ }
+ return S_OK;
+ }
+ case JSV_NUMBER: {
+ double n = get_number(val);
+
+ if(is_int32(n)) {
+ V_VT(retv) = VT_I4;
+ V_I4(retv) = n;
+ }else {
+ V_VT(retv) = VT_R8;
+ V_R8(retv) = n;
+ }
+
+ return S_OK;
+ }
+ case JSV_BOOL:
+ V_VT(retv) = VT_BOOL;
+ V_BOOL(retv) = get_bool(val) ? VARIANT_TRUE : VARIANT_FALSE;
+ return S_OK;
+ case JSV_VARIANT:
+ V_VT(retv) = VT_EMPTY;
+ return VariantCopy(retv, get_variant(val));
+ }
+
+ assert(0);
+ return E_FAIL;
+}
+
+/* ECMA-262 3rd Edition 9.1 */
+HRESULT to_primitive(script_ctx_t *ctx, jsval_t val, jsval_t *ret, hint_t hint)
+{
+ if(is_object_instance(val)) {
+ jsdisp_t *jsdisp;
+ jsval_t prim;
DISPID id;
- DISPPARAMS dp = {NULL, NULL, 0, 0};
HRESULT hres;
static const WCHAR toStringW[] = {'t','o','S','t','r','i','n','g',0};
static const WCHAR valueOfW[] = {'v','a','l','u','e','O','f',0};
- if(!V_DISPATCH(v)) {
- V_VT(ret) = VT_NULL;
- break;
+ if(!get_object(val)) {
+ *ret = jsval_null();
+ return S_OK;
}
- jsdisp = iface_to_jsdisp((IUnknown*)V_DISPATCH(v));
- if(!jsdisp) {
- V_VT(ret) = VT_EMPTY;
- return disp_propget(ctx, V_DISPATCH(v), DISPID_VALUE, ret, ei, NULL /*FIXME*/);
- }
+ jsdisp = iface_to_jsdisp((IUnknown*)get_object(val));
+ if(!jsdisp)
+ return disp_propget(ctx, get_object(val), DISPID_VALUE, ret);
if(hint == NO_HINT)
hint = is_class(jsdisp, JSCLASS_DATE) ? HINT_STRING : HINT_NUMBER;
hres = jsdisp_get_id(jsdisp, hint == HINT_STRING ? toStringW : valueOfW, 0, &id);
if(SUCCEEDED(hres)) {
- hres = jsdisp_call(jsdisp, id, DISPATCH_METHOD, &dp, ret, ei, NULL /*FIXME*/);
+ hres = jsdisp_call(jsdisp, id, DISPATCH_METHOD, 0, NULL, &prim);
if(FAILED(hres)) {
WARN("call error - forwarding exception\n");
jsdisp_release(jsdisp);
return hres;
- }
- else if(V_VT(ret) != VT_DISPATCH) {
+ }else if(!is_object_instance(prim)) {
jsdisp_release(jsdisp);
+ *ret = prim;
return S_OK;
+ }else {
+ IDispatch_Release(get_object(prim));
}
- else
- IDispatch_Release(V_DISPATCH(ret));
}
hres = jsdisp_get_id(jsdisp, hint == HINT_STRING ? valueOfW : toStringW, 0, &id);
if(SUCCEEDED(hres)) {
- hres = jsdisp_call(jsdisp, id, DISPATCH_METHOD, &dp, ret, ei, NULL /*FIXME*/);
+ hres = jsdisp_call(jsdisp, id, DISPATCH_METHOD, 0, NULL, &prim);
if(FAILED(hres)) {
WARN("call error - forwarding exception\n");
jsdisp_release(jsdisp);
return hres;
- }
- else if(V_VT(ret) != VT_DISPATCH) {
+ }else if(!is_object_instance(prim)) {
jsdisp_release(jsdisp);
+ *ret = prim;
return S_OK;
+ }else {
+ IDispatch_Release(get_object(prim));
}
- else
- IDispatch_Release(V_DISPATCH(ret));
}
jsdisp_release(jsdisp);
WARN("failed\n");
- return throw_type_error(ctx, ei, IDS_TO_PRIMITIVE, NULL);
- }
- default:
- FIXME("Unimplemented for vt %d\n", V_VT(v));
- return E_NOTIMPL;
+ return throw_type_error(ctx, JS_E_TO_PRIMITIVE, NULL);
}
- return S_OK;
+ return jsval_copy(val, ret);
+
}
/* ECMA-262 3rd Edition 9.2 */
-HRESULT to_boolean(VARIANT *v, VARIANT_BOOL *b)
+HRESULT to_boolean(jsval_t val, BOOL *ret)
{
- switch(V_VT(v)) {
- case VT_EMPTY:
- case VT_NULL:
- *b = VARIANT_FALSE;
- break;
- case VT_I4:
- *b = V_I4(v) ? VARIANT_TRUE : VARIANT_FALSE;
- break;
- case VT_R8:
- if(isnan(V_R8(v))) *b = VARIANT_FALSE;
- else *b = V_R8(v) ? VARIANT_TRUE : VARIANT_FALSE;
- break;
- case VT_BSTR:
- *b = V_BSTR(v) && *V_BSTR(v) ? VARIANT_TRUE : VARIANT_FALSE;
- break;
- case VT_DISPATCH:
- *b = V_DISPATCH(v) ? VARIANT_TRUE : VARIANT_FALSE;
- break;
- case VT_BOOL:
- *b = V_BOOL(v);
- break;
- default:
- FIXME("unimplemented for vt %d\n", V_VT(v));
+ switch(jsval_type(val)) {
+ case JSV_UNDEFINED:
+ case JSV_NULL:
+ *ret = FALSE;
+ return S_OK;
+ case JSV_OBJECT:
+ *ret = get_object(val) != NULL;
+ return S_OK;
+ case JSV_STRING:
+ *ret = jsstr_length(get_string(val)) != 0;
+ return S_OK;
+ case JSV_NUMBER:
+ *ret = !isnan(get_number(val)) && get_number(val);
+ return S_OK;
+ case JSV_BOOL:
+ *ret = get_bool(val);
+ return S_OK;
+ case JSV_VARIANT:
+ FIXME("unimplemented for variant %s\n", debugstr_variant(get_variant(val)));
return E_NOTIMPL;
}
- return S_OK;
+ assert(0);
+ return E_FAIL;
}
static int hex_to_int(WCHAR c)
}
/* ECMA-262 3rd Edition 9.3.1 */
-static HRESULT str_to_number(BSTR str, VARIANT *ret)
+static HRESULT str_to_number(jsstr_t *str, double *ret)
{
- const WCHAR *ptr = str;
+ const WCHAR *ptr = str->str;
BOOL neg = FALSE;
DOUBLE d = 0.0;
static const WCHAR infinityW[] = {'I','n','f','i','n','i','t','y'};
+ if(!ptr) {
+ *ret = 0;
+ return S_OK;
+ }
+
while(isspaceW(*ptr))
ptr++;
ptr++;
if(*ptr)
- num_set_nan(ret);
+ *ret = NAN;
else
- num_set_inf(ret, !neg);
+ *ret = neg ? -INFINITY : INFINITY;
return S_OK;
}
ptr++;
}
- num_set_val(ret, d);
+ *ret = d;
return S_OK;
}
ptr++;
if(*ptr) {
- num_set_nan(ret);
+ *ret = NAN;
return S_OK;
}
if(neg)
d = -d;
- num_set_val(ret, d);
+ *ret = d;
return S_OK;
}
/* ECMA-262 3rd Edition 9.3 */
-HRESULT to_number(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, VARIANT *ret)
+HRESULT to_number(script_ctx_t *ctx, jsval_t val, double *ret)
{
- switch(V_VT(v)) {
- case VT_EMPTY:
- num_set_nan(ret);
- break;
- case VT_NULL:
- V_VT(ret) = VT_I4;
- V_I4(ret) = 0;
- break;
- case VT_I4:
- case VT_R8:
- *ret = *v;
- break;
- case VT_BSTR:
- return str_to_number(V_BSTR(v), ret);
- case VT_DISPATCH: {
- VARIANT prim;
+ switch(jsval_type(val)) {
+ case JSV_UNDEFINED:
+ *ret = NAN;
+ return S_OK;
+ case JSV_NULL:
+ *ret = 0;
+ return S_OK;
+ case JSV_NUMBER:
+ *ret = get_number(val);
+ return S_OK;
+ case JSV_STRING:
+ return str_to_number(get_string(val), ret);
+ case JSV_OBJECT: {
+ jsval_t prim;
HRESULT hres;
- hres = to_primitive(ctx, v, ei, &prim, HINT_NUMBER);
+ hres = to_primitive(ctx, val, &prim, HINT_NUMBER);
if(FAILED(hres))
return hres;
- hres = to_number(ctx, &prim, ei, ret);
- VariantClear(&prim);
+ hres = to_number(ctx, prim, ret);
+ jsval_release(prim);
return hres;
}
- case VT_BOOL:
- V_VT(ret) = VT_I4;
- V_I4(ret) = V_BOOL(v) ? 1 : 0;
- break;
- default:
- FIXME("unimplemented for vt %d\n", V_VT(v));
+ case JSV_BOOL:
+ *ret = get_bool(val) ? 1 : 0;
+ return S_OK;
+ case JSV_VARIANT:
+ FIXME("unimplemented for variant %s\n", debugstr_variant(get_variant(val)));
return E_NOTIMPL;
- }
+ };
- return S_OK;
+ assert(0);
+ return E_FAIL;
}
/* ECMA-262 3rd Edition 9.4 */
-HRESULT to_integer(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, VARIANT *ret)
+HRESULT to_integer(script_ctx_t *ctx, jsval_t v, double *ret)
{
- VARIANT num;
+ double n;
HRESULT hres;
- hres = to_number(ctx, v, ei, &num);
+ hres = to_number(ctx, v, &n);
if(FAILED(hres))
return hres;
- if(V_VT(&num) == VT_I4) {
- *ret = num;
- }else if(isnan(V_R8(&num))) {
- V_VT(ret) = VT_I4;
- V_I4(ret) = 0;
- }else {
- num_set_val(ret, V_R8(&num) >= 0.0 ? floor(V_R8(&num)) : -floor(-V_R8(&num)));
- }
-
+ if(isnan(n))
+ *ret = 0;
+ else
+ *ret = n >= 0.0 ? floor(n) : -floor(-n);
return S_OK;
}
/* ECMA-262 3rd Edition 9.5 */
-HRESULT to_int32(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, INT *ret)
+HRESULT to_int32(script_ctx_t *ctx, jsval_t v, INT *ret)
{
- VARIANT num;
+ double n;
HRESULT hres;
- hres = to_number(ctx, v, ei, &num);
+ hres = to_number(ctx, v, &n);
if(FAILED(hres))
return hres;
- if(V_VT(&num) == VT_I4)
- *ret = V_I4(&num);
- else
- *ret = isnan(V_R8(&num)) || isinf(V_R8(&num)) ? 0 : (INT)V_R8(&num);
+ *ret = isnan(n) || isinf(n) ? 0 : n;
return S_OK;
}
/* ECMA-262 3rd Edition 9.6 */
-HRESULT to_uint32(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, DWORD *ret)
+HRESULT to_uint32(script_ctx_t *ctx, jsval_t val, DWORD *ret)
{
- VARIANT num;
+ INT32 n;
HRESULT hres;
- hres = to_number(ctx, v, ei, &num);
- if(FAILED(hres))
- return hres;
-
- if(V_VT(&num) == VT_I4)
- *ret = V_I4(&num);
- else
- *ret = isnan(V_R8(&num)) || isinf(V_R8(&num)) ? 0 : (DWORD)V_R8(&num);
- return S_OK;
+ hres = to_int32(ctx, val, &n);
+ if(SUCCEEDED(hres))
+ *ret = n;
+ return hres;
}
-static BSTR int_to_bstr(INT i)
+static jsstr_t *int_to_string(int i)
{
WCHAR buf[12], *p;
BOOL neg = FALSE;
if(!i) {
static const WCHAR zeroW[] = {'0',0};
- return SysAllocString(zeroW);
+ return jsstr_alloc(zeroW);
}
if(i < 0) {
else
p++;
- return SysAllocString(p);
+ return jsstr_alloc(p);
+}
+
+HRESULT double_to_string(double n, jsstr_t **str)
+{
+ const WCHAR InfinityW[] = {'-','I','n','f','i','n','i','t','y',0};
+
+ if(isnan(n)) {
+ *str = jsstr_nan();
+ }else if(isinf(n)) {
+ *str = jsstr_alloc(n<0 ? InfinityW : InfinityW+1);
+ }else if(is_int32(n)) {
+ *str = int_to_string(n);
+ }else {
+ VARIANT strv, v;
+ HRESULT hres;
+
+ /* FIXME: Don't use VariantChangeTypeEx */
+ V_VT(&v) = VT_R8;
+ V_R8(&v) = n;
+ V_VT(&strv) = VT_EMPTY;
+ hres = VariantChangeTypeEx(&strv, &v, MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT), 0, VT_BSTR);
+ if(FAILED(hres))
+ return hres;
+
+ *str = jsstr_alloc(V_BSTR(&strv));
+ SysFreeString(V_BSTR(&strv));
+ }
+
+ return *str ? S_OK : E_OUTOFMEMORY;
}
/* ECMA-262 3rd Edition 9.8 */
-HRESULT to_string(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, BSTR *str)
+HRESULT to_string(script_ctx_t *ctx, jsval_t val, jsstr_t **str)
{
- const WCHAR undefinedW[] = {'u','n','d','e','f','i','n','e','d',0};
const WCHAR nullW[] = {'n','u','l','l',0};
const WCHAR trueW[] = {'t','r','u','e',0};
const WCHAR falseW[] = {'f','a','l','s','e',0};
- const WCHAR NaNW[] = {'N','a','N',0};
- const WCHAR InfinityW[] = {'-','I','n','f','i','n','i','t','y',0};
- switch(V_VT(v)) {
- case VT_EMPTY:
- *str = SysAllocString(undefinedW);
- break;
- case VT_NULL:
- *str = SysAllocString(nullW);
- break;
- case VT_I4:
- *str = int_to_bstr(V_I4(v));
- break;
- case VT_R8: {
- if(isnan(V_R8(v)))
- *str = SysAllocString(NaNW);
- else if(isinf(V_R8(v)))
- *str = SysAllocString(V_R8(v)<0 ? InfinityW : InfinityW+1);
- else {
- VARIANT strv;
- HRESULT hres;
-
- V_VT(&strv) = VT_EMPTY;
- hres = VariantChangeTypeEx(&strv, v, MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT), 0, VT_BSTR);
- if(FAILED(hres))
- return hres;
-
- *str = V_BSTR(&strv);
- return S_OK;
- }
+ switch(jsval_type(val)) {
+ case JSV_UNDEFINED:
+ *str = jsstr_undefined();
+ return S_OK;
+ case JSV_NULL:
+ *str = jsstr_alloc(nullW);
break;
- }
- case VT_BSTR:
- *str = SysAllocString(V_BSTR(v));
+ case JSV_NUMBER:
+ return double_to_string(get_number(val), str);
+ case JSV_STRING:
+ *str = jsstr_addref(get_string(val));
break;
- case VT_DISPATCH: {
- VARIANT prim;
+ case JSV_OBJECT: {
+ jsval_t prim;
HRESULT hres;
- hres = to_primitive(ctx, v, ei, &prim, HINT_STRING);
+ hres = to_primitive(ctx, val, &prim, HINT_STRING);
if(FAILED(hres))
return hres;
- hres = to_string(ctx, &prim, ei, str);
- VariantClear(&prim);
+ hres = to_string(ctx, prim, str);
+ jsval_release(prim);
return hres;
}
- case VT_BOOL:
- *str = SysAllocString(V_BOOL(v) ? trueW : falseW);
+ case JSV_BOOL:
+ *str = jsstr_alloc(get_bool(val) ? trueW : falseW);
break;
default:
- FIXME("unsupported vt %d\n", V_VT(v));
+ FIXME("unsupported %s\n", debugstr_jsval(val));
return E_NOTIMPL;
}
}
/* ECMA-262 3rd Edition 9.9 */
-HRESULT to_object(script_ctx_t *ctx, VARIANT *v, IDispatch **disp)
+HRESULT to_object(script_ctx_t *ctx, jsval_t val, IDispatch **disp)
{
- DispatchEx *dispex;
+ jsdisp_t *dispex;
HRESULT hres;
- switch(V_VT(v)) {
- case VT_BSTR:
- hres = create_string(ctx, V_BSTR(v), SysStringLen(V_BSTR(v)), &dispex);
+ switch(jsval_type(val)) {
+ case JSV_STRING:
+ hres = create_string(ctx, get_string(val), &dispex);
if(FAILED(hres))
return hres;
- *disp = (IDispatch*)_IDispatchEx_(dispex);
+ *disp = to_disp(dispex);
break;
- case VT_I4:
- case VT_R8:
- hres = create_number(ctx, v, &dispex);
+ case JSV_NUMBER:
+ hres = create_number(ctx, get_number(val), &dispex);
if(FAILED(hres))
return hres;
- *disp = (IDispatch*)_IDispatchEx_(dispex);
+ *disp = to_disp(dispex);
break;
- case VT_DISPATCH:
- if(V_DISPATCH(v)) {
- IDispatch_AddRef(V_DISPATCH(v));
- *disp = V_DISPATCH(v);
+ case JSV_OBJECT:
+ if(get_object(val)) {
+ *disp = get_object(val);
+ IDispatch_AddRef(*disp);
}else {
- DispatchEx *obj;
+ jsdisp_t *obj;
hres = create_object(ctx, NULL, &obj);
if(FAILED(hres))
return hres;
- *disp = (IDispatch*)_IDispatchEx_(obj);
+ *disp = to_disp(obj);
}
break;
- case VT_BOOL:
- hres = create_bool(ctx, V_BOOL(v), &dispex);
+ case JSV_BOOL:
+ hres = create_bool(ctx, get_bool(val), &dispex);
if(FAILED(hres))
return hres;
- *disp = (IDispatch*)_IDispatchEx_(dispex);
+ *disp = to_disp(dispex);
+ break;
+ case JSV_UNDEFINED:
+ case JSV_NULL:
+ WARN("object expected\n");
+ return throw_type_error(ctx, JS_E_OBJECT_EXPECTED, NULL);
+ case JSV_VARIANT:
+ switch(V_VT(get_variant(val))) {
+ case VT_ARRAY|VT_VARIANT:
+ hres = create_vbarray(ctx, V_ARRAY(get_variant(val)), &dispex);
+ if(FAILED(hres))
+ return hres;
+
+ *disp = to_disp(dispex);
+ break;
+
+ default:
+ FIXME("Unsupported %s\n", debugstr_variant(get_variant(val)));
+ return E_NOTIMPL;
+ }
+ break;
+ }
+
+ return S_OK;
+}
+
+HRESULT variant_change_type(script_ctx_t *ctx, VARIANT *dst, VARIANT *src, VARTYPE vt)
+{
+ jsval_t val;
+ HRESULT hres;
+
+ clear_ei(ctx);
+ hres = variant_to_jsval(src, &val);
+ if(FAILED(hres))
+ return hres;
+
+ switch(vt) {
+ case VT_I2:
+ case VT_I4: {
+ INT i;
+
+ hres = to_int32(ctx, val, &i);
+ if(SUCCEEDED(hres)) {
+ if(vt == VT_I4)
+ V_I4(dst) = i;
+ else
+ V_I2(dst) = i;
+ }
+ break;
+ }
+ case VT_R8: {
+ double n;
+ hres = to_number(ctx, val, &n);
+ if(SUCCEEDED(hres))
+ V_R8(dst) = n;
+ break;
+ }
+ case VT_R4: {
+ double n;
+
+ hres = to_number(ctx, val, &n);
+ if(SUCCEEDED(hres))
+ V_R4(dst) = n;
+ break;
+ }
+ case VT_BOOL: {
+ BOOL b;
+
+ hres = to_boolean(val, &b);
+ if(SUCCEEDED(hres))
+ V_BOOL(dst) = b ? VARIANT_TRUE : VARIANT_FALSE;
+ break;
+ }
+ case VT_BSTR: {
+ jsstr_t *str;
+
+ hres = to_string(ctx, val, &str);
+ if(FAILED(hres))
+ break;
+
+ if(str->length_flags & JSSTR_FLAG_NULLBSTR) {
+ V_BSTR(dst) = NULL;
+ break;
+ }
+
+ V_BSTR(dst) = SysAllocStringLen(NULL, jsstr_length(str));
+ if(V_BSTR(dst))
+ jsstr_flush(str, V_BSTR(dst));
+ else
+ hres = E_OUTOFMEMORY;
+ break;
+ }
+ case VT_EMPTY:
+ hres = V_VT(src) == VT_EMPTY ? S_OK : E_NOTIMPL;
+ break;
+ case VT_NULL:
+ hres = V_VT(src) == VT_NULL ? S_OK : E_NOTIMPL;
break;
default:
- FIXME("unsupported vt %d\n", V_VT(v));
- return E_NOTIMPL;
+ FIXME("vt %d not implemented\n", vt);
+ hres = E_NOTIMPL;
}
+ jsval_release(val);
+ if(FAILED(hres))
+ return hres;
+
+ V_VT(dst) = vt;
+ return S_OK;
+}
+
+static inline JSCaller *impl_from_IServiceProvider(IServiceProvider *iface)
+{
+ return CONTAINING_RECORD(iface, JSCaller, IServiceProvider_iface);
+}
+
+static HRESULT WINAPI JSCaller_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv)
+{
+ JSCaller *This = impl_from_IServiceProvider(iface);
+
+ if(IsEqualGUID(&IID_IUnknown, riid)) {
+ TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
+ *ppv = &This->IServiceProvider_iface;
+ }else if(IsEqualGUID(&IID_IServiceProvider, riid)) {
+ TRACE("(%p)->(IID_IServiceProvider %p)\n", This, ppv);
+ *ppv = &This->IServiceProvider_iface;
+ }else {
+ WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
+ *ppv = NULL;
+ return E_NOINTERFACE;
+ }
+
+ IUnknown_AddRef((IUnknown*)*ppv);
+ return S_OK;
+}
+
+static ULONG WINAPI JSCaller_AddRef(IServiceProvider *iface)
+{
+ JSCaller *This = impl_from_IServiceProvider(iface);
+ LONG ref = InterlockedIncrement(&This->ref);
+
+ TRACE("(%p) ref=%d\n", This, ref);
+
+ return ref;
+}
+
+static ULONG WINAPI JSCaller_Release(IServiceProvider *iface)
+{
+ JSCaller *This = impl_from_IServiceProvider(iface);
+ LONG ref = InterlockedIncrement(&This->ref);
+
+ TRACE("(%p) ref=%d\n", This, ref);
+
+ if(!ref) {
+ assert(!This->ctx);
+ heap_free(This);
+ }
+
+ return ref;
+}
+
+static HRESULT WINAPI JSCaller_QueryService(IServiceProvider *iface, REFGUID guidService,
+ REFIID riid, void **ppv)
+{
+ JSCaller *This = impl_from_IServiceProvider(iface);
+
+ if(IsEqualGUID(guidService, &SID_VariantConversion) && This->ctx && This->ctx->active_script) {
+ TRACE("(%p)->(SID_VariantConversion)\n", This);
+ return IActiveScript_QueryInterface(This->ctx->active_script, riid, ppv);
+ }
+
+ FIXME("(%p)->(%s %s %p)\n", This, debugstr_guid(guidService), debugstr_guid(riid), ppv);
+
+ *ppv = NULL;
+ return E_NOINTERFACE;
+}
+
+static const IServiceProviderVtbl ServiceProviderVtbl = {
+ JSCaller_QueryInterface,
+ JSCaller_AddRef,
+ JSCaller_Release,
+ JSCaller_QueryService
+};
+
+HRESULT create_jscaller(script_ctx_t *ctx)
+{
+ JSCaller *ret;
+
+ ret = heap_alloc(sizeof(*ret));
+ if(!ret)
+ return E_OUTOFMEMORY;
+
+ ret->IServiceProvider_iface.lpVtbl = &ServiceProviderVtbl;
+ ret->ref = 1;
+ ret->ctx = ctx;
+
+ ctx->jscaller = ret;
return S_OK;
}
--- /dev/null
+/*
+ * Copyright 2012 Jacek Caban for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef JSVAL_H
+#define JSVAL_H
+
+#include "jsstr.h"
+
+/*
+ * jsval_t structure is used to represent JavaScript dynamically-typed values.
+ * It's a (type,value) pair, usually represented as a structure of enum (type)
+ * and union (value of given type). For both memory and speed performance, we
+ * use tricks allowing storing both values as a struct with size equal to
+ * size of double (that is 64-bit) on 32-bit systems. For that, we use the fact
+ * that NaN value representation has 52 (almost) free bits.
+ */
+
+#ifdef __i386__
+#define JSVAL_DOUBLE_LAYOUT_PTR32
+#endif
+
+#ifdef JSVAL_DOUBLE_LAYOUT_PTR32
+/* NaN exponent and our 0x80000 marker */
+#define JSV_VAL(x) (0x7ff80000|x)
+#else
+#define JSV_VAL(x) x
+#endif
+
+typedef enum {
+ JSV_UNDEFINED = JSV_VAL(1),
+ JSV_NULL = JSV_VAL(2),
+ JSV_OBJECT = JSV_VAL(3),
+ JSV_STRING = JSV_VAL(4),
+ JSV_NUMBER = JSV_VAL(5),
+ JSV_BOOL = JSV_VAL(6),
+ JSV_VARIANT = JSV_VAL(7)
+} jsval_type_t;
+
+struct _jsval_t {
+#ifdef JSVAL_DOUBLE_LAYOUT_PTR32
+ union {
+ double n;
+ struct {
+ union {
+ IDispatch *obj;
+ jsstr_t *str;
+ BOOL b;
+ VARIANT *v;
+ UINT_PTR as_uintptr;
+ } u;
+ jsval_type_t tag;
+ } s;
+ } u;
+#else
+ jsval_type_t type;
+ union {
+ IDispatch *obj;
+ jsstr_t *str;
+ double n;
+ BOOL b;
+ VARIANT *v;
+ } u;
+#endif
+};
+
+#ifdef JSVAL_DOUBLE_LAYOUT_PTR32
+
+C_ASSERT(sizeof(jsval_t) == sizeof(double));
+
+#define __JSVAL_TYPE(x) ((x).u.s.tag)
+#define __JSVAL_BOOL(x) ((x).u.s.u.b)
+#define __JSVAL_STR(x) ((x).u.s.u.str)
+#define __JSVAL_OBJ(x) ((x).u.s.u.obj)
+#define __JSVAL_VAR(x) ((x).u.s.u.v)
+
+#else
+
+#define __JSVAL_TYPE(x) ((x).type)
+#define __JSVAL_BOOL(x) ((x).u.b)
+#define __JSVAL_STR(x) ((x).u.str)
+#define __JSVAL_OBJ(x) ((x).u.obj)
+#define __JSVAL_VAR(x) ((x).u.v)
+
+#endif
+
+static inline jsval_t jsval_bool(BOOL b)
+{
+ jsval_t ret;
+ __JSVAL_TYPE(ret) = JSV_BOOL;
+ __JSVAL_BOOL(ret) = b;
+ return ret;
+}
+
+static inline jsval_t jsval_string(jsstr_t *str)
+{
+ jsval_t ret;
+ __JSVAL_TYPE(ret) = JSV_STRING;
+ __JSVAL_STR(ret) = str;
+ return ret;
+}
+
+static inline jsval_t jsval_disp(IDispatch *obj)
+{
+ jsval_t ret;
+ __JSVAL_TYPE(ret) = JSV_OBJECT;
+ __JSVAL_OBJ(ret) = obj;
+ return ret;
+}
+
+static inline jsval_t jsval_obj(jsdisp_t *obj)
+{
+ return jsval_disp(to_disp(obj));
+}
+
+static inline jsval_t jsval_null(void)
+{
+ jsval_t ret;
+ __JSVAL_TYPE(ret) = JSV_NULL;
+ return ret;
+}
+
+static inline jsval_t jsval_undefined(void)
+{
+ jsval_t ret;
+ __JSVAL_TYPE(ret) = JSV_UNDEFINED;
+ return ret;
+}
+
+static inline jsval_t jsval_number(double n)
+{
+ jsval_t ret;
+#ifdef JSVAL_DOUBLE_LAYOUT_PTR32
+ ret.u.n = n;
+ /* normalize NaN value */
+ if((ret.u.s.tag & 0x7ff00000) == 0x7ff00000) {
+ /* isinf */
+ if(ret.u.s.tag & 0xfffff) {
+ ret.u.s.tag = 0x7ff00000;
+ ret.u.s.u.as_uintptr = ~0;
+ }else if(ret.u.s.u.as_uintptr) {
+ ret.u.s.tag = 0x7ff00000;
+ }
+ }
+#else
+ ret.type = JSV_NUMBER;
+ ret.u.n = n;
+#endif
+ return ret;
+}
+
+static inline BOOL is_object_instance(jsval_t v)
+{
+ return __JSVAL_TYPE(v) == JSV_OBJECT;
+}
+
+static inline BOOL is_undefined(jsval_t v)
+{
+ return __JSVAL_TYPE(v) == JSV_UNDEFINED;
+}
+
+static inline BOOL is_null(jsval_t v)
+{
+ return __JSVAL_TYPE(v) == JSV_NULL;
+}
+
+static inline BOOL is_null_instance(jsval_t v)
+{
+ return is_null(v) || (is_object_instance(v) && !__JSVAL_OBJ(v));
+}
+
+static inline BOOL is_string(jsval_t v)
+{
+ return __JSVAL_TYPE(v) == JSV_STRING;
+}
+
+static inline BOOL is_number(jsval_t v)
+{
+#ifdef JSVAL_DOUBLE_LAYOUT_PTR32
+ return (v.u.s.tag & 0x7ff80000) != 0x7ff80000;
+#else
+ return v.type == JSV_NUMBER;
+#endif
+}
+
+static inline BOOL is_variant(jsval_t v)
+{
+ return __JSVAL_TYPE(v) == JSV_VARIANT;
+}
+
+static inline BOOL is_bool(jsval_t v)
+{
+ return __JSVAL_TYPE(v) == JSV_BOOL;
+}
+
+static inline jsval_type_t jsval_type(jsval_t v)
+{
+#ifdef JSVAL_DOUBLE_LAYOUT_PTR32
+ return is_number(v) ? JSV_NUMBER : v.u.s.tag;
+#else
+ return v.type;
+#endif
+}
+
+static inline IDispatch *get_object(jsval_t v)
+{
+ return __JSVAL_OBJ(v);
+}
+
+static inline double get_number(jsval_t v)
+{
+ return v.u.n;
+}
+
+static inline jsstr_t *get_string(jsval_t v)
+{
+ return __JSVAL_STR(v);
+}
+
+static inline VARIANT *get_variant(jsval_t v)
+{
+ return __JSVAL_VAR(v);
+}
+
+static inline BOOL get_bool(jsval_t v)
+{
+ return __JSVAL_BOOL(v);
+}
+
+HRESULT variant_to_jsval(VARIANT*,jsval_t*) DECLSPEC_HIDDEN;
+HRESULT jsval_to_variant(jsval_t,VARIANT*) DECLSPEC_HIDDEN;
+void jsval_release(jsval_t) DECLSPEC_HIDDEN;
+HRESULT jsval_copy(jsval_t,jsval_t*) DECLSPEC_HIDDEN;
+
+#endif
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
-#include <math.h>
+#include "config.h"
+#include "wine/port.h"
+
//#include <limits.h>
#include "jscript.h"
static const WCHAR trueW[] = {'t','r','u','e',0};
static const WCHAR tryW[] = {'t','r','y',0};
static const WCHAR typeofW[] = {'t','y','p','e','o','f',0};
-static const WCHAR undefinedW[] = {'u','n','d','e','f','i','n','e','d',0};
static const WCHAR varW[] = {'v','a','r',0};
static const WCHAR voidW[] = {'v','o','i','d',0};
static const WCHAR whileW[] = {'w','h','i','l','e',0};
static const struct {
const WCHAR *word;
int token;
+ BOOL no_nl;
} keywords[] = {
- {breakW, kBREAK},
+ {breakW, kBREAK, TRUE},
{caseW, kCASE},
{catchW, kCATCH},
- {continueW, kCONTINUE},
+ {continueW, kCONTINUE, TRUE},
{defaultW, kDEFAULT},
{deleteW, kDELETE},
{doW, kDO},
{instanceofW, kINSTANCEOF},
{newW, kNEW},
{nullW, kNULL},
- {returnW, kRETURN},
+ {returnW, kRETURN, TRUE},
{switchW, kSWITCH},
{thisW, kTHIS},
{throwW, kTHROW},
static int lex_error(parser_ctx_t *ctx, HRESULT hres)
{
- ctx->hres = JSCRIPT_ERROR|hres;
+ ctx->hres = hres;
ctx->lexer_error = TRUE;
return -1;
}
if(*p2 || (p1 < ctx->end && is_identifier_char(*p1)))
return 1;
- *lval = ctx->ptr;
+ if(lval)
+ *lval = ctx->ptr;
ctx->ptr = p1;
return 0;
}
i = (min+max)/2;
r = check_keyword(ctx, keywords[i].word, lval);
- if(!r)
+ if(!r) {
+ ctx->implicit_nl_semicolon = keywords[i].no_nl;
return keywords[i].token;
+ }
if(r > 0)
min = i+1;
return 0;
}
-static void skip_spaces(parser_ctx_t *ctx)
-{
- while(ctx->ptr < ctx->end && isspaceW(*ctx->ptr)) {
- if(is_endline(*ctx->ptr++))
- ctx->nl = TRUE;
- }
-}
-
static BOOL skip_html_comment(parser_ctx_t *ctx)
{
const WCHAR html_commentW[] = {'<','!','-','-',0};
static BOOL skip_comment(parser_ctx_t *ctx)
{
- if(ctx->ptr+1 >= ctx->end || *ctx->ptr != '/')
+ if(ctx->ptr+1 >= ctx->end)
return FALSE;
+ if(*ctx->ptr != '/') {
+ if(*ctx->ptr == '@' && ctx->ptr+2 < ctx->end && ctx->ptr[1] == '*' && ctx->ptr[2] == '/') {
+ ctx->ptr += 3;
+ return TRUE;
+ }
+
+ return FALSE;
+ }
+
switch(ctx->ptr[1]) {
case '*':
ctx->ptr += 2;
+ if(ctx->ptr+2 < ctx->end && *ctx->ptr == '@' && is_identifier_char(ctx->ptr[1]))
+ return FALSE;
while(ctx->ptr+1 < ctx->end && (ctx->ptr[0] != '*' || ctx->ptr[1] != '/'))
ctx->ptr++;
break;
case '/':
ctx->ptr += 2;
+ if(ctx->ptr+2 < ctx->end && *ctx->ptr == '@' && is_identifier_char(ctx->ptr[1]))
+ return FALSE;
while(ctx->ptr < ctx->end && !is_endline(*ctx->ptr))
ctx->ptr++;
break;
}
p++;
- c = 0;
switch(*p) {
case '\'':
case 'n':
c = '\n';
break;
- case 'v':
- c = '\v';
- break;
case 'f':
c = '\f';
break;
len = ctx->ptr-ptr;
*ret = wstr = parser_alloc(ctx, (len+1)*sizeof(WCHAR));
- memcpy(wstr, ptr, (len+1)*sizeof(WCHAR));
+ memcpy(wstr, ptr, len*sizeof(WCHAR));
wstr[len] = 0;
/* FIXME: unescape */
}
if(ctx->ptr == ctx->end)
- return lex_error(ctx, IDS_UNTERMINATED_STR);
+ return lex_error(ctx, JS_E_UNTERMINATED_STRING);
len = ctx->ptr-ptr;
*ret = wstr = parser_alloc(ctx, (len+1)*sizeof(WCHAR));
- memcpy(wstr, ptr, (len+1)*sizeof(WCHAR));
+ memcpy(wstr, ptr, len*sizeof(WCHAR));
wstr[len] = 0;
ctx->ptr++;
return tStringLiteral;
}
-static literal_t *alloc_int_literal(parser_ctx_t *ctx, LONG l)
+static literal_t *new_double_literal(parser_ctx_t *ctx, DOUBLE d)
{
literal_t *ret = parser_alloc(ctx, sizeof(literal_t));
- ret->type = LT_INT;
- ret->u.lval = l;
+ ret->type = LT_DOUBLE;
+ ret->u.dval = d;
+ return ret;
+}
+
+literal_t *new_boolean_literal(parser_ctx_t *ctx, BOOL bval)
+{
+ literal_t *ret = parser_alloc(ctx, sizeof(literal_t));
+
+ ret->type = LT_BOOL;
+ ret->u.bval = bval;
return ret;
}
LONGLONG d, hlp;
int exp = 0;
- if(ctx->ptr == ctx->end || (!isdigitW(*ctx->ptr) &&
- *ctx->ptr!='.' && *ctx->ptr!='e' && *ctx->ptr!='E')) {
- ERR("Illegal character\n");
- return 0;
- }
-
d = int_part;
while(ctx->ptr < ctx->end && isdigitW(*ctx->ptr)) {
hlp = d*10 + *(ctx->ptr++) - '0';
ctx->ptr++;
}
- if(*ctx->ptr == '.') ctx->ptr++;
+ if(*ctx->ptr == '.') {
+ ctx->ptr++;
- while(ctx->ptr < ctx->end && isdigitW(*ctx->ptr)) {
- hlp = d*10 + *(ctx->ptr++) - '0';
- if(d>LONGLONG_MAX/10 || hlp<0)
- break;
+ while(ctx->ptr < ctx->end && isdigitW(*ctx->ptr)) {
+ hlp = d*10 + *(ctx->ptr++) - '0';
+ if(d>LONGLONG_MAX/10 || hlp<0)
+ break;
- d = hlp;
- exp--;
+ d = hlp;
+ exp--;
+ }
+ while(ctx->ptr < ctx->end && isdigitW(*ctx->ptr))
+ ctx->ptr++;
}
- while(ctx->ptr < ctx->end && isdigitW(*ctx->ptr))
- ctx->ptr++;
if(ctx->ptr < ctx->end && (*ctx->ptr == 'e' || *ctx->ptr == 'E')) {
int sign = 1, e = 0;
else exp += e;
}
- *literal = parser_alloc(ctx, sizeof(literal_t));
- (*literal)->type = LT_DOUBLE;
- (*literal)->u.dval = (double)d*pow(10, exp);
-
+ *literal = new_double_literal(ctx, exp>=0 ? d*pow(10, exp) : d/pow(10, -exp));
return tNumericLiteral;
}
LONG l, d;
l = *ctx->ptr++ - '0';
- if(ctx->ptr == ctx->end) {
- *literal = alloc_int_literal(ctx, l);
- return tNumericLiteral;
- }
-
if(!l) {
if(*ctx->ptr == 'x' || *ctx->ptr == 'X') {
if(++ctx->ptr == ctx->end) {
- ERR("unexpexted end of file\n");
+ ERR("unexpected end of file\n");
return 0;
}
return lex_error(ctx, E_FAIL);
}
- *literal = alloc_int_literal(ctx, l);
+ *literal = new_double_literal(ctx, l);
return tNumericLiteral;
}
- if(isdigitW(*ctx->ptr) || is_identifier_char(*ctx->ptr)) {
+ if(is_identifier_char(*ctx->ptr)) {
WARN("wrong char after zero\n");
return lex_error(ctx, E_FAIL);
}
- *literal = alloc_int_literal(ctx, 0);
- }
-
- while(ctx->ptr < ctx->end && isdigitW(*ctx->ptr))
- {
- d = l*10 + *(ctx->ptr)-'0';
-
- /* Check for integer overflow */
- if (l > INT_MAX/10 || d < 0)
- return parse_double_literal(ctx, l, literal);
-
- l = d;
- ctx->ptr++;
- }
-
- if(ctx->ptr < ctx->end) {
- if(*ctx->ptr == '.' || *ctx->ptr == 'e' || *ctx->ptr == 'E')
- return parse_double_literal(ctx, l, literal);
-
- if(is_identifier_char(*ctx->ptr)) {
- WARN("unexpected identifier char\n");
- return lex_error(ctx, E_FAIL);
+ if(isdigitW(*ctx->ptr)) {
+ FIXME("octal literals not implemented\n");
+ return lex_error(ctx, E_NOTIMPL);
}
}
- *literal = alloc_int_literal(ctx, l);
- return tNumericLiteral;
+ return parse_double_literal(ctx, l, literal);
}
-int parser_lex(void *lval, parser_ctx_t *ctx)
+static int next_token(parser_ctx_t *ctx, void *lval)
{
- int ret;
-
- ctx->nl = ctx->ptr == ctx->begin;
-
do {
- skip_spaces(ctx);
+ while(ctx->ptr < ctx->end && isspaceW(*ctx->ptr)) {
+ if(is_endline(*ctx->ptr++))
+ ctx->nl = TRUE;
+ }
if(ctx->ptr == ctx->end)
- return 0;
+ return tEOF;
}while(skip_comment(ctx) || skip_html_comment(ctx));
+ if(ctx->implicit_nl_semicolon) {
+ if(ctx->nl)
+ return ';';
+ ctx->implicit_nl_semicolon = FALSE;
+ }
+
if(isalphaW(*ctx->ptr)) {
- ret = check_keywords(ctx, lval);
+ int ret = check_keywords(ctx, lval);
if(ret)
return ret;
case '_':
case '$':
return parse_identifier(ctx, lval);
+
+ case '@':
+ return '@';
}
WARN("unexpected char '%c' %d\n", *ctx->ptr, *ctx->ptr);
return 0;
}
+struct _cc_var_t {
+ BOOL is_num;
+ union {
+ BOOL b;
+ DOUBLE n;
+ } u;
+ struct _cc_var_t *next;
+ unsigned name_len;
+ WCHAR name[0];
+};
+
+void release_cc(cc_ctx_t *cc)
+{
+ cc_var_t *iter, *next;
+
+ for(iter = cc->vars; iter; iter = next) {
+ next = iter->next;
+ heap_free(iter);
+ }
+
+ heap_free(cc);
+}
+
+static BOOL add_cc_var(cc_ctx_t *cc, const WCHAR *name, cc_var_t *v)
+{
+ cc_var_t *new_v;
+ unsigned len;
+
+ len = strlenW(name);
+
+ new_v = heap_alloc(sizeof(cc_var_t) + (len+1)*sizeof(WCHAR));
+ if(!new_v)
+ return FALSE;
+
+ memcpy(new_v, v, sizeof(*v));
+ memcpy(new_v->name, name, (len+1)*sizeof(WCHAR));
+ new_v->name_len = len;
+ new_v->next = cc->vars;
+ cc->vars = new_v;
+ return TRUE;
+}
+
+static cc_var_t *find_cc_var(cc_ctx_t *cc, const WCHAR *name, unsigned name_len)
+{
+ cc_var_t *iter;
+
+ for(iter = cc->vars; iter; iter = iter->next) {
+ if(iter->name_len == name_len && !memcmp(iter->name, name, name_len*sizeof(WCHAR)))
+ return iter;
+ }
+
+ return NULL;
+}
+
+static int init_cc(parser_ctx_t *ctx)
+{
+ cc_ctx_t *cc;
+ cc_var_t v;
+
+ static const WCHAR _win32W[] = {'_','w','i','n','3','2',0};
+ static const WCHAR _win64W[] = {'_','w','i','n','6','4',0};
+ static const WCHAR _x86W[] = {'_','x','8','6',0};
+ static const WCHAR _amd64W[] = {'_','a','m','d','6','4',0};
+ static const WCHAR _jscriptW[] = {'_','j','s','c','r','i','p','t',0};
+ static const WCHAR _jscript_buildW[] = {'_','j','s','c','r','i','p','t','_','b','u','i','l','d',0};
+ static const WCHAR _jscript_versionW[] = {'_','j','s','c','r','i','p','t','_','v','e','r','s','i','o','n',0};
+
+ if(ctx->script->cc)
+ return 0;
+
+ cc = heap_alloc(sizeof(cc_ctx_t));
+ if(!cc)
+ return lex_error(ctx, E_OUTOFMEMORY);
+
+ cc->vars = NULL;
+ v.is_num = FALSE;
+ v.u.b = TRUE;
+ if(!add_cc_var(cc, _jscriptW, &v)
+ || !add_cc_var(cc, sizeof(void*) == 8 ? _win64W : _win32W, &v)
+ || !add_cc_var(cc, sizeof(void*) == 8 ? _amd64W : _x86W, &v)) {
+ release_cc(cc);
+ return lex_error(ctx, E_OUTOFMEMORY);
+ }
+
+ v.is_num = TRUE;
+ v.u.n = JSCRIPT_BUILD_VERSION;
+ if(!add_cc_var(cc, _jscript_buildW, &v)) {
+ release_cc(cc);
+ return lex_error(ctx, E_OUTOFMEMORY);
+ }
+
+ v.u.n = JSCRIPT_MAJOR_VERSION + (DOUBLE)JSCRIPT_MINOR_VERSION/10.0;
+ if(!add_cc_var(cc, _jscript_versionW, &v)) {
+ release_cc(cc);
+ return lex_error(ctx, E_OUTOFMEMORY);
+ }
+
+ ctx->script->cc = cc;
+ return 0;
+}
+
+static int cc_token(parser_ctx_t *ctx, void *lval)
+{
+ unsigned id_len = 0;
+ cc_var_t *var;
+
+ static const WCHAR cc_onW[] = {'c','c','_','o','n',0};
+ static const WCHAR setW[] = {'s','e','t',0};
+ static const WCHAR elifW[] = {'e','l','i','f',0};
+ static const WCHAR endW[] = {'e','n','d',0};
+
+ ctx->ptr++;
+
+ if(!check_keyword(ctx, cc_onW, NULL))
+ return init_cc(ctx);
+
+ if(!check_keyword(ctx, setW, NULL)) {
+ FIXME("@set not implemented\n");
+ return lex_error(ctx, E_NOTIMPL);
+ }
+
+ if(!check_keyword(ctx, ifW, NULL)) {
+ FIXME("@if not implemented\n");
+ return lex_error(ctx, E_NOTIMPL);
+ }
+
+ if(!check_keyword(ctx, elifW, NULL)) {
+ FIXME("@elif not implemented\n");
+ return lex_error(ctx, E_NOTIMPL);
+ }
+
+ if(!check_keyword(ctx, elseW, NULL)) {
+ FIXME("@else not implemented\n");
+ return lex_error(ctx, E_NOTIMPL);
+ }
+
+ if(!check_keyword(ctx, endW, NULL)) {
+ FIXME("@end not implemented\n");
+ return lex_error(ctx, E_NOTIMPL);
+ }
+
+ if(!ctx->script->cc)
+ return lex_error(ctx, JS_E_DISABLED_CC);
+
+ while(ctx->ptr+id_len < ctx->end && is_identifier_char(ctx->ptr[id_len]))
+ id_len++;
+ if(!id_len)
+ return '@';
+
+ TRACE("var %s\n", debugstr_wn(ctx->ptr, id_len));
+
+ var = find_cc_var(ctx->script->cc, ctx->ptr, id_len);
+ ctx->ptr += id_len;
+ if(!var || var->is_num) {
+ *(literal_t**)lval = new_double_literal(ctx, var ? var->u.n : NAN);
+ return tNumericLiteral;
+ }
+
+ *(literal_t**)lval = new_boolean_literal(ctx, var->u.b);
+ return tBooleanLiteral;
+}
+
+int parser_lex(void *lval, parser_ctx_t *ctx)
+{
+ int ret;
+
+ ctx->nl = ctx->ptr == ctx->begin;
+
+ do {
+ ret = next_token(ctx, lval);
+ } while(ret == '@' && !(ret = cc_token(ctx, lval)));
+
+ return ret;
+}
+
literal_t *parse_regexp(parser_ctx_t *ctx)
{
const WCHAR *re, *flags_ptr;
+ BOOL in_class = FALSE;
DWORD re_len, flags;
literal_t *ret;
HRESULT hres;
TRACE("\n");
- while(*ctx->ptr != '/')
- ctx->ptr--;
+ while(*--ctx->ptr != '/');
+ /* Simple regexp pre-parser; '/' if used in char class does not terminate regexp literal */
re = ++ctx->ptr;
- while(ctx->ptr < ctx->end && *ctx->ptr != '/') {
- if(*ctx->ptr++ == '\\' && ctx->ptr < ctx->end)
- ctx->ptr++;
+ while(ctx->ptr < ctx->end) {
+ if(*ctx->ptr == '\\') {
+ if(++ctx->ptr == ctx->end)
+ break;
+ }else if(in_class) {
+ if(*ctx->ptr == '\n')
+ break;
+ if(*ctx->ptr == ']')
+ in_class = FALSE;
+ }else {
+ if(*ctx->ptr == '/')
+ break;
+
+ if(*ctx->ptr == '[')
+ in_class = TRUE;
+ }
+ ctx->ptr++;
}
- if(ctx->ptr == ctx->end) {
- WARN("unexpected end of file\n");
+ if(ctx->ptr == ctx->end || *ctx->ptr != '/') {
+ WARN("pre-parsing failed\n");
return NULL;
}
static const WCHAR sqrtW[] = {'s','q','r','t',0};
static const WCHAR tanW[] = {'t','a','n',0};
-static HRESULT math_constant(DOUBLE val, WORD flags, VARIANT *retv)
-{
- switch(flags) {
- case DISPATCH_PROPERTYGET:
- V_VT(retv) = VT_R8;
- V_R8(retv) = val;
- return S_OK;
- case DISPATCH_PROPERTYPUT:
- return S_OK;
- }
-
- FIXME("unhandled flags %x\n", flags);
- return E_NOTIMPL;
-}
-
-/* ECMA-262 3rd Edition 15.8.1.1 */
-static HRESULT Math_E(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
-{
- TRACE("\n");
- return math_constant(M_E, flags, retv);
-}
-
-/* ECMA-262 3rd Edition 15.8.1.4 */
-static HRESULT Math_LOG2E(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
-{
- TRACE("\n");
- return math_constant(M_LOG2E, flags, retv);
-}
-
-/* ECMA-262 3rd Edition 15.8.1.4 */
-static HRESULT Math_LOG10E(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
-{
- TRACE("\n");
- return math_constant(M_LOG10E, flags, retv);
-}
-
-static HRESULT Math_LN2(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
-{
- TRACE("\n");
- return math_constant(M_LN2, flags, retv);
-}
-
-static HRESULT Math_LN10(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
-{
- TRACE("\n");
- return math_constant(M_LN10, flags, retv);
-}
-
-/* ECMA-262 3rd Edition 15.8.1.6 */
-static HRESULT Math_PI(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
-{
- TRACE("\n");
- return math_constant(M_PI, flags, retv);
-}
-
-static HRESULT Math_SQRT2(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
-{
- TRACE("\n");
- return math_constant(M_SQRT2, flags, retv);
-}
-
-static HRESULT Math_SQRT1_2(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
-{
- TRACE("\n");
- return math_constant(M_SQRT1_2, flags, retv);
-}
-
/* ECMA-262 3rd Edition 15.8.2.12 */
-static HRESULT Math_abs(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT Math_abs(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- VARIANT v;
- DOUBLE d;
+ double d;
HRESULT hres;
TRACE("\n");
- if(!arg_cnt(dp)) {
- if(retv)
- num_set_nan(retv);
+ if(!argc) {
+ if(r)
+ *r = jsval_number(NAN);
return S_OK;
}
- hres = to_number(ctx, get_arg(dp, 0), ei, &v);
+ hres = to_number(ctx, argv[0], &d);
if(FAILED(hres))
return hres;
- d = num_val(&v);
- if(retv)
- num_set_val(retv, d < 0.0 ? -d : d);
+ if(r)
+ *r = jsval_number(d < 0.0 ? -d : d);
return S_OK;
}
-static HRESULT Math_acos(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT Math_acos(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- VARIANT v;
+ double x;
HRESULT hres;
TRACE("\n");
- if(!arg_cnt(dp)) {
- if(retv) num_set_nan(retv);
+ if(!argc) {
+ if(r)
+ *r = jsval_number(NAN);
return S_OK;
}
- hres = to_number(ctx, get_arg(dp, 0), ei, &v);
+ hres = to_number(ctx, argv[0], &x);
if(FAILED(hres))
return hres;
- if(retv) num_set_val(retv, acos(num_val(&v)));
+ if(r)
+ *r = jsval_number(x < -1.0 || x > 1.0 ? NAN : acos(x));
return S_OK;
}
-static HRESULT Math_asin(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT Math_asin(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- VARIANT v;
+ double x;
HRESULT hres;
TRACE("\n");
- if(!arg_cnt(dp)) {
- if(retv) num_set_nan(retv);
+ if(!argc) {
+ if(r)
+ *r = jsval_number(NAN);
return S_OK;
}
- hres = to_number(ctx, get_arg(dp, 0), ei, &v);
+ hres = to_number(ctx, argv[0], &x);
if(FAILED(hres))
return hres;
- if(retv) num_set_val(retv, asin(num_val(&v)));
+ if(r)
+ *r = jsval_number(x < -1.0 || x > 1.0 ? NAN : asin(x));
return S_OK;
}
-static HRESULT Math_atan(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT Math_atan(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- VARIANT v;
+ double x;
HRESULT hres;
TRACE("\n");
- if(!arg_cnt(dp)) {
- if(retv) num_set_nan(retv);
+ if(!argc) {
+ if(r)
+ *r = jsval_number(NAN);
return S_OK;
}
- hres = to_number(ctx, get_arg(dp, 0), ei, &v);
+ hres = to_number(ctx, argv[0], &x);
if(FAILED(hres))
return hres;
- if(retv) num_set_val(retv, atan(num_val(&v)));
+ if(r)
+ *r = jsval_number(atan(x));
return S_OK;
}
-static HRESULT Math_atan2(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT Math_atan2(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- VARIANT v1, v2;
+ double x, y;
HRESULT hres;
TRACE("\n");
- if(arg_cnt(dp)<2) {
- if(retv) num_set_nan(retv);
+ if(argc<2) {
+ if(r)
+ *r = jsval_number(NAN);
return S_OK;
}
- hres = to_number(ctx, get_arg(dp, 0), ei, &v1);
+ hres = to_number(ctx, argv[0], &y);
if(FAILED(hres))
return hres;
- hres = to_number(ctx, get_arg(dp, 1), ei, &v2);
+ hres = to_number(ctx, argv[1], &x);
if(FAILED(hres))
return hres;
- if(retv) num_set_val(retv, atan2(num_val(&v1), num_val(&v2)));
+ if(r)
+ *r = jsval_number(atan2(y, x));
return S_OK;
}
/* ECMA-262 3rd Edition 15.8.2.6 */
-static HRESULT Math_ceil(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT Math_ceil(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- VARIANT v;
+ double x;
HRESULT hres;
TRACE("\n");
- if(!arg_cnt(dp)) {
- if(retv)
- num_set_nan(retv);
+ if(!argc) {
+ if(r)
+ *r = jsval_number(NAN);
return S_OK;
}
- hres = to_number(ctx, get_arg(dp, 0), ei, &v);
+ hres = to_number(ctx, argv[0], &x);
if(FAILED(hres))
return hres;
- if(retv)
- num_set_val(retv, ceil(num_val(&v)));
+ if(r)
+ *r = jsval_number(ceil(x));
return S_OK;
}
-static HRESULT Math_cos(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT Math_cos(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- VARIANT v;
+ double x;
HRESULT hres;
TRACE("\n");
- if(!arg_cnt(dp)) {
- if(retv) num_set_nan(retv);
+ if(!argc) {
+ if(r)
+ *r = jsval_number(NAN);
return S_OK;
}
- hres = to_number(ctx, get_arg(dp, 0), ei, &v);
+ hres = to_number(ctx, argv[0], &x);
if(FAILED(hres))
return hres;
- if(retv) num_set_val(retv, cos(num_val(&v)));
+ if(r)
+ *r = jsval_number(cos(x));
return S_OK;
}
-static HRESULT Math_exp(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT Math_exp(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- VARIANT v;
+ double x;
HRESULT hres;
TRACE("\n");
- if(!arg_cnt(dp)) {
- if(retv) num_set_nan(retv);
+ if(!argc) {
+ if(r)
+ *r = jsval_number(NAN);
return S_OK;
}
- hres = to_number(ctx, get_arg(dp, 0), ei, &v);
+ hres = to_number(ctx, argv[0], &x);
if(FAILED(hres))
return hres;
- if(retv) num_set_val(retv, exp(num_val(&v)));
+ if(r)
+ *r = jsval_number(exp(x));
return S_OK;
}
-static HRESULT Math_floor(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT Math_floor(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- VARIANT v;
+ double x;
HRESULT hres;
TRACE("\n");
- if(!arg_cnt(dp)) {
- if(retv)
- num_set_nan(retv);
+ if(!argc) {
+ if(r)
+ *r = jsval_number(NAN);
return S_OK;
}
- hres = to_number(ctx, get_arg(dp, 0), ei, &v);
+ hres = to_number(ctx, argv[0], &x);
if(FAILED(hres))
return hres;
- if(retv)
- num_set_val(retv, floor(num_val(&v)));
+ if(r)
+ *r = jsval_number(floor(x));
return S_OK;
}
-static HRESULT Math_log(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT Math_log(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- VARIANT v;
+ double x;
HRESULT hres;
TRACE("\n");
- if(!arg_cnt(dp)) {
- if(retv)
- num_set_nan(retv);
+ if(!argc) {
+ if(r)
+ *r = jsval_number(NAN);
return S_OK;
}
- hres = to_number(ctx, get_arg(dp, 0), ei, &v);
+ hres = to_number(ctx, argv[0], &x);
if(FAILED(hres))
return hres;
- if(retv)
- num_set_val(retv, log(num_val(&v)));
+ if(r)
+ *r = jsval_number(x < -0.0 ? NAN : log(x));
return S_OK;
}
/* ECMA-262 3rd Edition 15.8.2.11 */
-static HRESULT Math_max(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT Math_max(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
DOUBLE max, d;
- VARIANT v;
DWORD i;
HRESULT hres;
TRACE("\n");
- if(!arg_cnt(dp)) {
- if(retv)
- num_set_inf(retv, FALSE);
+ if(!argc) {
+ if(r)
+ *r = jsval_number(-INFINITY);
return S_OK;
}
- hres = to_number(ctx, get_arg(dp, 0), ei, &v);
+ hres = to_number(ctx, argv[0], &max);
if(FAILED(hres))
return hres;
- max = num_val(&v);
- for(i=1; i < arg_cnt(dp); i++) {
- hres = to_number(ctx, get_arg(dp, i), ei, &v);
+ for(i=1; i < argc; i++) {
+ hres = to_number(ctx, argv[i], &d);
if(FAILED(hres))
return hres;
- d = num_val(&v);
if(d > max || isnan(d))
max = d;
}
- if(retv)
- num_set_val(retv, max);
+ if(r)
+ *r = jsval_number(max);
return S_OK;
}
/* ECMA-262 3rd Edition 15.8.2.12 */
-static HRESULT Math_min(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT Math_min(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
DOUBLE min, d;
- VARIANT v;
DWORD i;
HRESULT hres;
TRACE("\n");
- if(!arg_cnt(dp)) {
- if(retv)
- num_set_inf(retv, TRUE);
+ if(!argc) {
+ if(r)
+ *r = jsval_number(INFINITY);
return S_OK;
}
- hres = to_number(ctx, get_arg(dp, 0), ei, &v);
+ hres = to_number(ctx, argv[0], &min);
if(FAILED(hres))
return hres;
- min = num_val(&v);
- for(i=1; i < arg_cnt(dp); i++) {
- hres = to_number(ctx, get_arg(dp, i), ei, &v);
+ for(i=1; i < argc; i++) {
+ hres = to_number(ctx, argv[i], &d);
if(FAILED(hres))
return hres;
- d = num_val(&v);
if(d < min || isnan(d))
min = d;
}
- if(retv)
- num_set_val(retv, min);
+ if(r)
+ *r = jsval_number(min);
return S_OK;
}
/* ECMA-262 3rd Edition 15.8.2.13 */
-static HRESULT Math_pow(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT Math_pow(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- VARIANT x, y;
+ double x, y;
HRESULT hres;
TRACE("\n");
- if(arg_cnt(dp) < 2) {
- if(retv) num_set_nan(retv);
+ if(argc < 2) {
+ if(r)
+ *r = jsval_number(NAN);
return S_OK;
}
- hres = to_number(ctx, get_arg(dp, 0), ei, &x);
+ hres = to_number(ctx, argv[0], &x);
if(FAILED(hres))
return hres;
- hres = to_number(ctx, get_arg(dp, 1), ei, &y);
+ hres = to_number(ctx, argv[1], &y);
if(FAILED(hres))
return hres;
- if(retv)
- num_set_val(retv, pow(num_val(&x), num_val(&y)));
+ if(r)
+ *r = jsval_number(pow(x, y));
return S_OK;
}
/* ECMA-262 3rd Edition 15.8.2.14 */
-static HRESULT Math_random(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT Math_random(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- UINT r;
+ UINT x;
TRACE("\n");
- if(!RtlGenRandom(&r, sizeof(r)))
+ if(!RtlGenRandom(&x, sizeof(x)))
return E_UNEXPECTED;
- if(retv)
- num_set_val(retv, (DOUBLE)r/(DOUBLE)UINT_MAX);
-
+ if(r)
+ *r = jsval_number((double)x/(double)UINT_MAX);
return S_OK;
}
/* ECMA-262 3rd Edition 15.8.2.15 */
-static HRESULT Math_round(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT Math_round(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- VARIANT v;
+ double x;
HRESULT hres;
TRACE("\n");
- if(!arg_cnt(dp)) {
- num_set_nan(retv);
+ if(!argc) {
+ if(r)
+ *r = jsval_number(NAN);
return S_OK;
}
- hres = to_number(ctx, get_arg(dp, 0), ei, &v);
+ hres = to_number(ctx, argv[0], &x);
if(FAILED(hres))
return hres;
- if(retv)
- num_set_val(retv, floor(num_val(&v)+0.5));
+ if(r)
+ *r = jsval_number(floor(x+0.5));
return S_OK;
}
-static HRESULT Math_sin(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT Math_sin(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- VARIANT v;
+ double x;
HRESULT hres;
TRACE("\n");
- if(!arg_cnt(dp)) {
- if(retv) num_set_nan(retv);
+ if(!argc) {
+ if(r)
+ *r = jsval_number(NAN);
return S_OK;
}
- hres = to_number(ctx, get_arg(dp, 0), ei, &v);
+ hres = to_number(ctx, argv[0], &x);
if(FAILED(hres))
return hres;
- if(retv) num_set_val(retv, sin(num_val(&v)));
+ if(r)
+ *r = jsval_number(sin(x));
return S_OK;
}
-static HRESULT Math_sqrt(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT Math_sqrt(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- VARIANT v;
+ double x;
HRESULT hres;
TRACE("\n");
- if(!arg_cnt(dp)) {
- if(retv) num_set_nan(retv);
+ if(!argc) {
+ if(r)
+ *r = jsval_number(NAN);
return S_OK;
}
- hres = to_number(ctx, get_arg(dp, 0), ei, &v);
+ hres = to_number(ctx, argv[0], &x);
if(FAILED(hres))
return hres;
- if(retv) num_set_val(retv, sqrt(num_val(&v)));
+ if(r)
+ *r = jsval_number(sqrt(x));
return S_OK;
}
-static HRESULT Math_tan(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT Math_tan(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- VARIANT v;
+ double x;
HRESULT hres;
TRACE("\n");
- if(!arg_cnt(dp)) {
- if(retv) num_set_nan(retv);
+ if(!argc) {
+ if(r)
+ *r = jsval_number(NAN);
return S_OK;
}
- hres = to_number(ctx, get_arg(dp, 0), ei, &v);
+ hres = to_number(ctx, argv[0], &x);
if(FAILED(hres))
return hres;
- if(retv) num_set_val(retv, tan(num_val(&v)));
+ if(r)
+ *r = jsval_number(tan(x));
return S_OK;
}
static const builtin_prop_t Math_props[] = {
- {EW, Math_E, 0},
- {LN10W, Math_LN10, 0},
- {LN2W, Math_LN2, 0},
- {LOG10EW, Math_LOG10E, 0},
- {LOG2EW, Math_LOG2E, 0},
- {PIW, Math_PI, 0},
- {SQRT1_2W, Math_SQRT1_2, 0},
- {SQRT2W, Math_SQRT2, 0},
{absW, Math_abs, PROPF_METHOD|1},
{acosW, Math_acos, PROPF_METHOD|1},
{asinW, Math_asin, PROPF_METHOD|1},
NULL
};
-HRESULT create_math(script_ctx_t *ctx, DispatchEx **ret)
+HRESULT create_math(script_ctx_t *ctx, jsdisp_t **ret)
{
- DispatchEx *math;
+ jsdisp_t *math;
+ unsigned i;
HRESULT hres;
- math = heap_alloc_zero(sizeof(DispatchEx));
+ struct {
+ const WCHAR *name;
+ DOUBLE val;
+ }constants[] = {
+ {EW, M_E}, /* ECMA-262 3rd Edition 15.8.1.1 */
+ {LN10W, M_LN10}, /* ECMA-262 3rd Edition 15.8.1.2 */
+ {LN2W, M_LN2}, /* ECMA-262 3rd Edition 15.8.1.3 */
+ {LOG2EW, M_LOG2E}, /* ECMA-262 3rd Edition 15.8.1.4 */
+ {LOG10EW, M_LOG10E}, /* ECMA-262 3rd Edition 15.8.1.5 */
+ {PIW, M_PI}, /* ECMA-262 3rd Edition 15.8.1.6 */
+ {SQRT1_2W, M_SQRT1_2}, /* ECMA-262 3rd Edition 15.8.1.7 */
+ {SQRT2W, M_SQRT2}, /* ECMA-262 3rd Edition 15.8.1.8 */
+ };
+
+ math = heap_alloc_zero(sizeof(jsdisp_t));
if(!math)
return E_OUTOFMEMORY;
return hres;
}
+ for(i=0; i < sizeof(constants)/sizeof(*constants); i++) {
+ hres = jsdisp_propput_const(math, constants[i].name, jsval_number(constants[i].val));
+ if(FAILED(hres)) {
+ jsdisp_release(math);
+ return hres;
+ }
+ }
+
*ret = math;
return S_OK;
}
#include <wine/port.h>
//#include <math.h>
+#include <assert.h>
#include "jscript.h"
WINE_DEFAULT_DEBUG_CHANNEL(jscript);
typedef struct {
- DispatchEx dispex;
+ jsdisp_t dispex;
- VARIANT num;
+ double value;
} NumberInstance;
static const WCHAR toStringW[] = {'t','o','S','t','r','i','n','g',0};
static const WCHAR valueOfW[] = {'v','a','l','u','e','O','f',0};
#define NUMBER_TOSTRING_BUF_SIZE 64
+#define NUMBER_DTOA_SIZE 18
static inline NumberInstance *number_from_vdisp(vdisp_t *vdisp)
{
return is_vclass(jsthis, JSCLASS_NUMBER) ? number_from_vdisp(jsthis) : NULL;
}
+static inline void dtoa(double d, WCHAR *buf, int size, int *dec_point)
+{
+ ULONGLONG l;
+ int i;
+
+ /* TODO: this function should print doubles with bigger precision */
+ assert(size>=2 && size<=NUMBER_DTOA_SIZE && d>=0);
+
+ if(d == 0)
+ *dec_point = 0;
+ else
+ *dec_point = floor(log10(d));
+ l = d*pow(10, size-*dec_point-1);
+
+ if(l%10 >= 5)
+ l = l/10+1;
+ else
+ l /= 10;
+
+ buf[size-1] = 0;
+ for(i=size-2; i>=0; i--) {
+ buf[i] = '0'+l%10;
+ l /= 10;
+ }
+
+ /* log10 was wrong by 1 or rounding changed number of digits */
+ if(l) {
+ (*dec_point)++;
+ memmove(buf+1, buf, size-2);
+ buf[0] = '0'+l;
+ }else if(buf[0]=='0' && buf[1]>='1' && buf[1]<='9') {
+ (*dec_point)--;
+ memmove(buf, buf+1, size-2);
+ buf[size-2] = '0';
+ }
+}
+
+static inline jsstr_t *number_to_fixed(double val, int prec)
+{
+ WCHAR buf[NUMBER_DTOA_SIZE];
+ int dec_point, size, buf_size, buf_pos;
+ BOOL neg = FALSE;
+ jsstr_t *ret;
+ WCHAR *str;
+
+ TRACE("%lf %d\n", val, prec);
+
+ if(val < 0) {
+ neg = TRUE;
+ val = -val;
+ }
+
+ if(val >= 1)
+ buf_size = log10(val)+prec+2;
+ else
+ buf_size = prec ? prec+1 : 2;
+ if(buf_size > NUMBER_DTOA_SIZE)
+ buf_size = NUMBER_DTOA_SIZE;
+
+ dtoa(val, buf, buf_size, &dec_point);
+ dec_point++;
+ size = 0;
+ if(neg)
+ size++;
+ if(dec_point > 0)
+ size += dec_point;
+ else
+ size++;
+ if(prec)
+ size += prec+1;
+
+ ret = jsstr_alloc_buf(size);
+ if(!ret)
+ return NULL;
+
+ str = ret->str;
+ size = buf_pos = 0;
+ if(neg)
+ str[size++] = '-';
+ if(dec_point > 0) {
+ for(;buf_pos<buf_size-1 && dec_point; dec_point--)
+ str[size++] = buf[buf_pos++];
+ }else {
+ str[size++] = '0';
+ }
+ for(; dec_point>0; dec_point--)
+ str[size++] = '0';
+ if(prec) {
+ str[size++] = '.';
+
+ for(; dec_point<0 && prec; dec_point++, prec--)
+ str[size++] = '0';
+ for(; buf_pos<buf_size-1 && prec; prec--)
+ str[size++] = buf[buf_pos++];
+ for(; prec; prec--) {
+ str[size++] = '0';
+ }
+ }
+ str[size++] = 0;
+ return ret;
+}
+
+static inline jsstr_t *number_to_exponential(double val, int prec)
+{
+ WCHAR buf[NUMBER_DTOA_SIZE], *pbuf;
+ int dec_point, size, buf_size, exp_size = 1;
+ BOOL neg = FALSE;
+ jsstr_t *ret;
+ WCHAR *str;
+
+ if(val < 0) {
+ neg = TRUE;
+ val = -val;
+ }
+
+ 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);
+ buf_size--;
+ if(prec == -1)
+ for(; buf_size>1 && buf[buf_size-1]=='0'; buf_size--)
+ buf[buf_size-1] = 0;
+
+ size = 10;
+ while(dec_point>=size || dec_point<=-size) {
+ size *= 10;
+ exp_size++;
+ }
+
+ if(buf_size == 1)
+ size = buf_size+2+exp_size; /* 2 = strlen(e+) */
+ else if(prec == -1)
+ size = buf_size+3+exp_size; /* 3 = strlen(.e+) */
+ else
+ size = prec+4+exp_size; /* 4 = strlen(0.e+) */
+ if(neg)
+ size++;
+
+ ret = jsstr_alloc_buf(size);
+ if(!ret)
+ return NULL;
+
+ str = ret->str;
+ size = 0;
+ pbuf = buf;
+ if(neg)
+ str[size++] = '-';
+ str[size++] = *pbuf++;
+ if(buf_size != 1) {
+ str[size++] = '.';
+ while(*pbuf)
+ str[size++] = *pbuf++;
+ for(; prec>buf_size-1; prec--)
+ str[size++] = '0';
+ }
+ str[size++] = 'e';
+ if(dec_point >= 0) {
+ str[size++] = '+';
+ }else {
+ str[size++] = '-';
+ dec_point = -dec_point;
+ }
+ size += exp_size;
+ do {
+ str[--size] = '0'+dec_point%10;
+ dec_point /= 10;
+ }while(dec_point>0);
+ size += exp_size;
+ str[size] = 0;
+
+ return ret;
+}
+
/* ECMA-262 3rd Edition 15.7.4.2 */
-static HRESULT Number_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT Number_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
NumberInstance *number;
INT radix = 10;
DOUBLE val;
- BSTR str;
+ jsstr_t *str;
HRESULT hres;
TRACE("\n");
if(!(number = number_this(jsthis)))
- return throw_type_error(ctx, ei, IDS_NOT_NUM, NULL);
+ return throw_type_error(ctx, JS_E_NUMBER_EXPECTED, NULL);
- if(arg_cnt(dp)) {
- hres = to_int32(ctx, get_arg(dp, 0), ei, &radix);
+ if(argc) {
+ hres = to_int32(ctx, argv[0], &radix);
if(FAILED(hres))
return hres;
if(radix<2 || radix>36)
- return throw_type_error(ctx, ei, IDS_INVALID_CALL_ARG, NULL);
+ return throw_type_error(ctx, JS_E_INVALIDARG, NULL);
}
- if(V_VT(&number->num) == VT_I4)
- val = V_I4(&number->num);
- else
- val = V_R8(&number->num);
+ val = number->value;
if(radix==10 || isnan(val) || isinf(val)) {
- hres = to_string(ctx, &number->num, ei, &str);
+ hres = to_string(ctx, jsval_number(val), &str);
if(FAILED(hres))
return hres;
- }
- else {
+ }else {
INT idx = 0;
DOUBLE integ, frac, log_radix = 0;
WCHAR buf[NUMBER_TOSTRING_BUF_SIZE+16];
if(exp) {
if(log_radix==0)
- buf[idx++] = '\0';
+ buf[idx] = 0;
else {
static const WCHAR formatW[] = {'(','e','%','c','%','d',')',0};
WCHAR ch;
}
else buf[idx] = '\0';
- str = SysAllocString(buf);
+ str = jsstr_alloc(buf);
if(!str)
return E_OUTOFMEMORY;
}
- if(retv) {
- V_VT(retv) = VT_BSTR;
- V_BSTR(retv) = str;
- }else {
- SysFreeString(str);
- }
+ if(r)
+ *r = jsval_string(str);
+ else
+ jsstr_release(str);
return S_OK;
}
-static HRESULT Number_toLocaleString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT Number_toLocaleString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
FIXME("\n");
return E_NOTIMPL;
}
-static HRESULT Number_toFixed(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT Number_toFixed(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- FIXME("\n");
- return E_NOTIMPL;
+ NumberInstance *number;
+ DOUBLE val;
+ INT prec = 0;
+ jsstr_t *str;
+ HRESULT hres;
+
+ TRACE("\n");
+
+ if(!(number = number_this(jsthis)))
+ return throw_type_error(ctx, JS_E_NUMBER_EXPECTED, NULL);
+
+ if(argc) {
+ hres = to_int32(ctx, argv[0], &prec);
+ if(FAILED(hres))
+ return hres;
+
+ if(prec<0 || prec>20)
+ return throw_range_error(ctx, JS_E_FRACTION_DIGITS_OUT_OF_RANGE, NULL);
+ }
+
+ val = number->value;
+ if(isinf(val) || isnan(val)) {
+ hres = to_string(ctx, jsval_number(val), &str);
+ if(FAILED(hres))
+ return hres;
+ }else {
+ str = number_to_fixed(val, prec);
+ if(!str)
+ return E_OUTOFMEMORY;
+ }
+
+ if(r)
+ *r = jsval_string(str);
+ else
+ jsstr_release(str);
+ return S_OK;
}
-static HRESULT Number_toExponential(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT Number_toExponential(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- FIXME("\n");
- return E_NOTIMPL;
+ NumberInstance *number;
+ DOUBLE val;
+ INT prec = 0;
+ jsstr_t *str;
+ HRESULT hres;
+
+ TRACE("\n");
+
+ if(!(number = number_this(jsthis)))
+ return throw_type_error(ctx, JS_E_NUMBER_EXPECTED, NULL);
+
+ if(argc) {
+ hres = to_int32(ctx, argv[0], &prec);
+ if(FAILED(hres))
+ return hres;
+
+ if(prec<0 || prec>20)
+ return throw_range_error(ctx, JS_E_FRACTION_DIGITS_OUT_OF_RANGE, NULL);
+ }
+
+ val = number->value;
+ if(isinf(val) || isnan(val)) {
+ hres = to_string(ctx, jsval_number(val), &str);
+ if(FAILED(hres))
+ return hres;
+ }else {
+ if(!prec)
+ prec--;
+ str = number_to_exponential(val, prec);
+ if(!str)
+ return E_OUTOFMEMORY;
+ }
+
+ if(r)
+ *r = jsval_string(str);
+ else
+ jsstr_release(str);
+ return S_OK;
}
-static HRESULT Number_toPrecision(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT Number_toPrecision(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- FIXME("\n");
- return E_NOTIMPL;
+ NumberInstance *number;
+ INT prec = 0, size;
+ jsstr_t *str;
+ DOUBLE val;
+ HRESULT hres;
+
+ if(!(number = number_this(jsthis)))
+ return throw_type_error(ctx, JS_E_NUMBER_EXPECTED, NULL);
+
+ if(argc) {
+ hres = to_int32(ctx, argv[0], &prec);
+ if(FAILED(hres))
+ return hres;
+
+ if(prec<1 || prec>21)
+ return throw_range_error(ctx, JS_E_PRECISION_OUT_OF_RANGE, NULL);
+ }
+
+ val = number->value;
+ if(isinf(val) || isnan(val) || !prec) {
+ hres = to_string(ctx, jsval_number(val), &str);
+ if(FAILED(hres))
+ return hres;
+ }else {
+ if(val != 0)
+ size = floor(log10(val>0 ? val : -val)) + 1;
+ else
+ size = 1;
+
+ if(size > prec)
+ str = number_to_exponential(val, prec-1);
+ else
+ str = number_to_fixed(val, prec-size);
+ if(!str)
+ return E_OUTOFMEMORY;
+ }
+
+ if(r)
+ *r = jsval_string(str);
+ else
+ jsstr_release(str);
+ return S_OK;
}
-static HRESULT Number_valueOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT Number_valueOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
NumberInstance *number;
TRACE("\n");
if(!(number = number_this(jsthis)))
- return throw_type_error(ctx, ei, IDS_NOT_NUM, NULL);
+ return throw_type_error(ctx, JS_E_NUMBER_EXPECTED, NULL);
- if(retv)
- *retv = number->num;
+ if(r)
+ *r = jsval_number(number->value);
return S_OK;
}
-static HRESULT Number_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT Number_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
NumberInstance *number = number_from_vdisp(jsthis);
switch(flags) {
case INVOKE_FUNC:
- return throw_type_error(ctx, ei, IDS_NOT_FUNC, NULL);
+ return throw_type_error(ctx, JS_E_FUNCTION_EXPECTED, NULL);
case DISPATCH_PROPERTYGET:
- *retv = number->num;
+ *r = jsval_number(number->value);
break;
default:
NULL
};
-static HRESULT NumberConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static const builtin_info_t NumberInst_info = {
+ JSCLASS_NUMBER,
+ {NULL, Number_value, 0},
+ 0, NULL,
+ NULL,
+ NULL
+};
+
+static HRESULT NumberConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- VARIANT num;
+ double n;
HRESULT hres;
TRACE("\n");
switch(flags) {
case INVOKE_FUNC:
- if(!arg_cnt(dp)) {
- if(retv) {
- V_VT(retv) = VT_I4;
- V_I4(retv) = 0;
- }
+ if(!argc) {
+ if(r)
+ *r = jsval_number(0);
return S_OK;
}
- hres = to_number(ctx, get_arg(dp, 0), ei, &num);
+ hres = to_number(ctx, argv[0], &n);
if(FAILED(hres))
return hres;
- if(retv)
- *retv = num;
+ if(r)
+ *r = jsval_number(n);
break;
case DISPATCH_CONSTRUCT: {
- DispatchEx *obj;
+ jsdisp_t *obj;
- if(arg_cnt(dp)) {
- hres = to_number(ctx, get_arg(dp, 0), ei, &num);
+ if(argc) {
+ hres = to_number(ctx, argv[0], &n);
if(FAILED(hres))
return hres;
}else {
- V_VT(&num) = VT_I4;
- V_I4(&num) = 0;
+ n = 0;
}
- hres = create_number(ctx, &num, &obj);
+ hres = create_number(ctx, n, &obj);
if(FAILED(hres))
return hres;
- V_VT(retv) = VT_DISPATCH;
- V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(obj);
+ *r = jsval_obj(obj);
break;
}
default:
return S_OK;
}
-static HRESULT alloc_number(script_ctx_t *ctx, DispatchEx *object_prototype, NumberInstance **ret)
+static HRESULT alloc_number(script_ctx_t *ctx, jsdisp_t *object_prototype, NumberInstance **ret)
{
NumberInstance *number;
HRESULT hres;
if(object_prototype)
hres = init_dispex(&number->dispex, ctx, &Number_info, object_prototype);
else
- hres = init_dispex_from_constr(&number->dispex, ctx, &Number_info, ctx->number_constr);
- if(FAILED(hres))
+ hres = init_dispex_from_constr(&number->dispex, ctx, &NumberInst_info, ctx->number_constr);
+ if(FAILED(hres)) {
+ heap_free(number);
return hres;
+ }
*ret = number;
return S_OK;
}
-HRESULT create_number_constr(script_ctx_t *ctx, DispatchEx *object_prototype, DispatchEx **ret)
+HRESULT create_number_constr(script_ctx_t *ctx, jsdisp_t *object_prototype, jsdisp_t **ret)
{
NumberInstance *number;
HRESULT hres;
if(FAILED(hres))
return hres;
- V_VT(&number->num) = VT_I4;
- hres = create_builtin_function(ctx, NumberConstr_value, NumberW, NULL,
+ number->value = 0;
+ hres = create_builtin_constructor(ctx, NumberConstr_value, NumberW, NULL,
PROPF_CONSTR|1, &number->dispex, ret);
jsdisp_release(&number->dispex);
return hres;
}
-HRESULT create_number(script_ctx_t *ctx, VARIANT *num, DispatchEx **ret)
+HRESULT create_number(script_ctx_t *ctx, double value, jsdisp_t **ret)
{
NumberInstance *number;
HRESULT hres;
if(FAILED(hres))
return hres;
- number->num = *num;
+ number->value = value;
*ret = &number->dispex;
return S_OK;
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
+#include <assert.h>
+
#include "jscript.h"
#include <wine/debug.h>
static const WCHAR default_valueW[] = {'[','o','b','j','e','c','t',' ','O','b','j','e','c','t',']',0};
-static HRESULT Object_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT Object_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- DispatchEx *jsdisp;
+ jsdisp_t *jsdisp;
const WCHAR *str;
static const WCHAR formatW[] = {'[','o','b','j','e','c','t',' ','%','s',']',0};
static const WCHAR regexpW[] = {'R','e','g','E','x','p',0};
static const WCHAR stringW[] = {'S','t','r','i','n','g',0};
/* Keep in sync with jsclass_t enum */
- static const WCHAR *names[] = {objectW, arrayW, booleanW, dateW, errorW,
- functionW, NULL, mathW, numberW, objectW, regexpW, stringW, objectW};
+ static const WCHAR *names[] = {NULL, arrayW, booleanW, dateW, errorW,
+ functionW, NULL, mathW, numberW, objectW, regexpW, stringW, objectW, objectW};
TRACE("\n");
}else if(names[jsdisp->builtin_info->class]) {
str = names[jsdisp->builtin_info->class];
}else {
+ assert(jsdisp->builtin_info->class != JSCLASS_NONE);
FIXME("jdisp->builtin_info->class = %d\n", jsdisp->builtin_info->class);
return E_FAIL;
}
- if(retv) {
- V_VT(retv) = VT_BSTR;
- V_BSTR(retv) = SysAllocStringLen(NULL, 9+strlenW(str));
- if(!V_BSTR(retv))
+ if(r) {
+ jsstr_t *ret;
+
+ ret = jsstr_alloc_buf(9+strlenW(str));
+ if(!ret)
return E_OUTOFMEMORY;
- sprintfW(V_BSTR(retv), formatW, str);
+ sprintfW(ret->str, formatW, str);
+ *r = jsval_string(ret);
}
return S_OK;
}
-static HRESULT Object_toLocaleString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT Object_toLocaleString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- DISPPARAMS params = {NULL, NULL, 0, 0};
-
TRACE("\n");
if(!is_jsdisp(jsthis)) {
return E_FAIL;
}
- return jsdisp_call_name(jsthis->u.jsdisp, toStringW, DISPATCH_METHOD, ¶ms, retv, ei, sp);
+ return jsdisp_call_name(jsthis->u.jsdisp, toStringW, DISPATCH_METHOD, 0, NULL, r);
}
-static HRESULT Object_valueOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT Object_valueOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
TRACE("\n");
- if(retv) {
+ if(r) {
IDispatch_AddRef(jsthis->u.disp);
-
- V_VT(retv) = VT_DISPATCH;
- V_DISPATCH(retv) = jsthis->u.disp;
+ *r = jsval_disp(jsthis->u.disp);
}
-
return S_OK;
}
-static HRESULT Object_hasOwnProperty(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT Object_hasOwnProperty(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- FIXME("\n");
- return E_NOTIMPL;
+ jsstr_t *name;
+ DISPID id;
+ BSTR bstr;
+ HRESULT hres;
+
+ TRACE("\n");
+
+ if(!argc) {
+ if(r)
+ *r = jsval_bool(FALSE);
+ return S_OK;
+ }
+
+ hres = to_string(ctx, argv[0], &name);
+ if(FAILED(hres))
+ return hres;
+
+ if(is_jsdisp(jsthis)) {
+ BOOL result;
+
+ hres = jsdisp_is_own_prop(jsthis->u.jsdisp, name->str, &result);
+ jsstr_release(name);
+ if(FAILED(hres))
+ return hres;
+
+ if(r)
+ *r = jsval_bool(result);
+ return S_OK;
+ }
+
+
+ bstr = SysAllocStringLen(NULL, jsstr_length(name));
+ if(bstr)
+ jsstr_flush(name, bstr);
+ jsstr_release(name);
+ if(!bstr)
+ return E_OUTOFMEMORY;
+
+ if(is_dispex(jsthis))
+ hres = IDispatchEx_GetDispID(jsthis->u.dispex, bstr, make_grfdex(ctx, fdexNameCaseSensitive), &id);
+ else
+ hres = IDispatch_GetIDsOfNames(jsthis->u.disp, &IID_NULL, &bstr, 1, ctx->lcid, &id);
+
+ SysFreeString(bstr);
+ if(r)
+ *r = jsval_bool(SUCCEEDED(hres));
+ return S_OK;
}
-static HRESULT Object_propertyIsEnumerable(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT Object_propertyIsEnumerable(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- FIXME("\n");
- return E_NOTIMPL;
+ jsstr_t *name;
+ BOOL ret;
+ HRESULT hres;
+
+ TRACE("\n");
+
+ if(argc != 1) {
+ FIXME("argc %d not supported\n", argc);
+ return E_NOTIMPL;
+ }
+
+ if(!is_jsdisp(jsthis)) {
+ FIXME("Host object this\n");
+ return E_FAIL;
+ }
+
+ hres = to_string(ctx, argv[0], &name);
+ if(FAILED(hres))
+ return hres;
+
+ hres = jsdisp_is_enumerable(jsthis->u.jsdisp, name->str, &ret);
+ jsstr_release(name);
+ if(FAILED(hres))
+ return hres;
+
+ if(r)
+ *r = jsval_bool(ret);
+ return S_OK;
}
-static HRESULT Object_isPrototypeOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT Object_isPrototypeOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
FIXME("\n");
return E_NOTIMPL;
}
-static HRESULT Object_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT Object_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
TRACE("\n");
switch(flags) {
case INVOKE_FUNC:
- return throw_type_error(ctx, ei, IDS_NOT_FUNC, NULL);
- case DISPATCH_PROPERTYGET:
- V_VT(retv) = VT_BSTR;
- V_BSTR(retv) = SysAllocString(default_valueW);
- if(!V_BSTR(retv))
+ return throw_type_error(ctx, JS_E_FUNCTION_EXPECTED, NULL);
+ case DISPATCH_PROPERTYGET: {
+ jsstr_t *ret = jsstr_alloc(default_valueW);
+ if(!ret)
return E_OUTOFMEMORY;
+ *r = jsval_string(ret);
break;
+ }
default:
FIXME("unimplemented flags %x\n", flags);
return E_NOTIMPL;
return S_OK;
}
-static void Object_destructor(DispatchEx *dispex)
+static void Object_destructor(jsdisp_t *dispex)
{
heap_free(dispex);
}
NULL
};
-static HRESULT ObjectConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static const builtin_info_t ObjectInst_info = {
+ JSCLASS_OBJECT,
+ {NULL, Object_value, 0},
+ 0, NULL,
+ Object_destructor,
+ NULL
+};
+
+static HRESULT ObjectConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
HRESULT hres;
switch(flags) {
case DISPATCH_METHOD:
- if(arg_cnt(dp)) {
- VARIANT *arg = get_arg(dp,0);
-
- if(V_VT(arg) != VT_EMPTY && V_VT(arg) != VT_NULL) {
+ if(argc) {
+ if(!is_undefined(argv[0]) && !is_null(argv[0]) && (!is_object_instance(argv[0]) || get_object(argv[0]))) {
IDispatch *disp;
- hres = to_object(ctx, arg, &disp);
+ hres = to_object(ctx, argv[0], &disp);
if(FAILED(hres))
return hres;
- if(retv) {
- V_VT(retv) = VT_DISPATCH;
- V_DISPATCH(retv) = disp;
- }else {
+ if(r)
+ *r = jsval_disp(disp);
+ else
IDispatch_Release(disp);
- }
return S_OK;
}
}
/* fall through */
case DISPATCH_CONSTRUCT: {
- DispatchEx *obj;
+ jsdisp_t *obj;
hres = create_object(ctx, NULL, &obj);
if(FAILED(hres))
return hres;
- V_VT(retv) = VT_DISPATCH;
- V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(obj);
+ if(r)
+ *r = jsval_obj(obj);
+ else
+ jsdisp_release(obj);
break;
}
return S_OK;
}
-HRESULT create_object_constr(script_ctx_t *ctx, DispatchEx *object_prototype, DispatchEx **ret)
+HRESULT create_object_constr(script_ctx_t *ctx, jsdisp_t *object_prototype, jsdisp_t **ret)
{
static const WCHAR ObjectW[] = {'O','b','j','e','c','t',0};
- return create_builtin_function(ctx, ObjectConstr_value, ObjectW, NULL, PROPF_CONSTR,
+ return create_builtin_constructor(ctx, ObjectConstr_value, ObjectW, NULL, PROPF_CONSTR,
object_prototype, ret);
}
-HRESULT create_object_prototype(script_ctx_t *ctx, DispatchEx **ret)
+HRESULT create_object_prototype(script_ctx_t *ctx, jsdisp_t **ret)
{
return create_dispex(ctx, &Object_info, NULL, ret);
}
-HRESULT create_object(script_ctx_t *ctx, DispatchEx *constr, DispatchEx **ret)
+HRESULT create_object(script_ctx_t *ctx, jsdisp_t *constr, jsdisp_t **ret)
{
- DispatchEx *object;
+ jsdisp_t *object;
HRESULT hres;
- object = heap_alloc_zero(sizeof(DispatchEx));
+ object = heap_alloc_zero(sizeof(jsdisp_t));
if(!object)
return E_OUTOFMEMORY;
- hres = init_dispex_from_constr(object, ctx, &Object_info, constr ? constr : ctx->object_constr);
+ hres = init_dispex_from_constr(object, ctx, &ObjectInst_info, constr ? constr : ctx->object_constr);
if(FAILED(hres)) {
heap_free(object);
return hres;
#include "jscript.h"
#include "engine.h"
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(jscript);
+
#define YYLEX_PARAM ctx
#define YYPARSE_PARAM ctx
static BOOL explicit_error(parser_ctx_t*,void*,WCHAR);
static BOOL allow_auto_semicolon(parser_ctx_t*);
static void program_parsed(parser_ctx_t*,source_elements_t*);
-static source_elements_t *function_body_parsed(parser_ctx_t*,source_elements_t*);
typedef struct _statement_list_t {
statement_t *head;
static literal_t *new_string_literal(parser_ctx_t*,const WCHAR*);
static literal_t *new_null_literal(parser_ctx_t*);
-static literal_t *new_boolean_literal(parser_ctx_t*,VARIANT_BOOL);
typedef struct _property_list_t {
prop_val_t *head;
static variable_list_t *new_variable_list(parser_ctx_t*,variable_declaration_t*);
static variable_list_t *variable_list_add(parser_ctx_t*,variable_list_t*,variable_declaration_t*);
+static void *new_statement(parser_ctx_t*,statement_type_t,size_t);
static statement_t *new_block_statement(parser_ctx_t*,statement_list_t*);
static statement_t *new_var_statement(parser_ctx_t*,variable_list_t*);
-static statement_t *new_empty_statement(parser_ctx_t*);
static statement_t *new_expression_statement(parser_ctx_t*,expression_t*);
static statement_t *new_if_statement(parser_ctx_t*,expression_t*,statement_t*,statement_t*);
static statement_t *new_while_statement(parser_ctx_t*,BOOL,expression_t*,statement_t*);
static parameter_list_t *new_parameter_list(parser_ctx_t*,const WCHAR*);
static parameter_list_t *parameter_list_add(parser_ctx_t*,parameter_list_t*,const WCHAR*);
-static void push_func(parser_ctx_t*);
-static inline void pop_func(parser_ctx_t *ctx)
-{
- ctx->func_stack = ctx->func_stack->next;
-}
-
+static void *new_expression(parser_ctx_t *ctx,expression_type_t,size_t);
static expression_t *new_function_expression(parser_ctx_t*,const WCHAR*,parameter_list_t*,
source_elements_t*,const WCHAR*,DWORD);
static expression_t *new_binary_expression(parser_ctx_t*,expression_type_t,expression_t*,expression_t*);
static expression_t *new_unary_expression(parser_ctx_t*,expression_type_t,expression_t*);
static expression_t *new_conditional_expression(parser_ctx_t*,expression_t*,expression_t*,expression_t*);
-static expression_t *new_array_expression(parser_ctx_t*,expression_t*,expression_t*);
static expression_t *new_member_expression(parser_ctx_t*,expression_t*,const WCHAR*);
static expression_t *new_new_expression(parser_ctx_t*,expression_t*,argument_list_t*);
static expression_t *new_call_expression(parser_ctx_t*,expression_t*,argument_list_t*);
-static expression_t *new_this_expression(parser_ctx_t*);
static expression_t *new_identifier_expression(parser_ctx_t*,const WCHAR*);
static expression_t *new_literal_expression(parser_ctx_t*,literal_t*);
static expression_t *new_array_literal_expression(parser_ctx_t*,element_list_t*,int);
/* Line 189 of yacc.c */
-#line 210 "parser.tab.c"
+#line 205 "parser.tab.c"
/* Enabling traces. */
#ifndef YYDEBUG
tShiftOper = 295,
tRelOper = 296,
tNumericLiteral = 297,
- tStringLiteral = 298,
- LOWER_THAN_ELSE = 299
+ tBooleanLiteral = 298,
+ tStringLiteral = 299,
+ tEOF = 300,
+ LOWER_THAN_ELSE = 301
};
#endif
{
/* Line 214 of yacc.c */
-#line 150 "parser.y"
+#line 145 "parser.y"
int ival;
const WCHAR *srcptr;
/* Line 214 of yacc.c */
-#line 313 "parser.tab.c"
+#line 310 "parser.tab.c"
} YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
/* Line 264 of yacc.c */
-#line 325 "parser.tab.c"
+#line 322 "parser.tab.c"
#ifdef short
# undef short
/* YYFINAL -- State number of the termination state. */
#define YYFINAL 3
/* YYLAST -- Last index in YYTABLE. */
-#define YYLAST 1030
+#define YYLAST 1053
/* YYNTOKENS -- Number of terminals. */
-#define YYNTOKENS 67
+#define YYNTOKENS 69
/* YYNNTS -- Number of nonterminals. */
#define YYNNTS 95
/* YYNRULES -- Number of rules. */
-#define YYNRULES 214
+#define YYNRULES 215
/* YYNRULES -- Number of states. */
-#define YYNSTATES 373
+#define YYNSTATES 375
/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
#define YYUNDEFTOK 2
-#define YYMAXUTOK 299
+#define YYMAXUTOK 301
#define YYTRANSLATE(YYX) \
((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 61, 2, 2, 2, 59, 54, 2,
- 65, 66, 57, 55, 47, 56, 64, 58, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 50, 49,
- 2, 48, 2, 51, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 63, 2, 2, 2, 61, 56, 2,
+ 67, 68, 59, 57, 49, 58, 66, 60, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 52, 51,
+ 2, 50, 2, 53, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 62, 2, 63, 53, 2, 2, 2, 2, 2,
+ 2, 64, 2, 65, 55, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 46, 52, 37, 60, 2, 2, 2,
+ 2, 2, 2, 48, 54, 37, 62, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
- 35, 36, 38, 39, 40, 41, 42, 43, 44, 45
+ 35, 36, 38, 39, 40, 41, 42, 43, 44, 45,
+ 46, 47
};
#if YYDEBUG
YYRHS. */
static const yytype_uint16 yyprhs[] =
{
- 0, 0, 3, 6, 8, 9, 10, 13, 22, 24,
- 26, 28, 32, 33, 35, 37, 39, 41, 43, 45,
- 47, 49, 51, 53, 55, 57, 59, 61, 63, 65,
- 67, 70, 71, 73, 77, 80, 84, 86, 90, 92,
- 96, 99, 102, 103, 105, 108, 109, 111, 114, 116,
- 119, 127, 133, 141, 147, 148, 149, 161, 162, 163,
- 176, 184, 193, 197, 201, 205, 211, 215, 221, 225,
- 231, 232, 234, 236, 239, 244, 248, 252, 256, 260,
- 265, 271, 274, 275, 277, 279, 281, 283, 287, 288,
- 290, 292, 296, 298, 300, 302, 306, 310, 312, 316,
- 320, 322, 328, 330, 336, 338, 342, 344, 348, 350,
- 354, 356, 360, 362, 366, 368, 372, 374, 378, 380,
- 384, 386, 390, 392, 396, 398, 402, 404, 408, 410,
- 414, 418, 422, 424, 428, 432, 434, 438, 440, 444,
- 448, 450, 454, 458, 462, 464, 467, 470, 473, 476,
- 479, 482, 485, 488, 491, 493, 496, 499, 501, 503,
- 505, 508, 510, 512, 517, 521, 525, 528, 531, 536,
- 540, 543, 547, 549, 553, 555, 557, 559, 561, 563,
- 567, 570, 574, 578, 584, 587, 592, 594, 597, 598,
- 600, 603, 607, 611, 617, 619, 621, 623, 624, 626,
- 628, 630, 632, 634, 636, 638, 640, 642, 644, 646,
- 648, 650, 652, 654, 656
+ 0, 0, 3, 7, 9, 10, 11, 14, 23, 25,
+ 27, 29, 33, 34, 36, 38, 40, 42, 44, 46,
+ 48, 50, 52, 54, 56, 58, 60, 62, 64, 66,
+ 68, 71, 72, 74, 78, 81, 85, 87, 91, 93,
+ 97, 100, 103, 104, 106, 109, 110, 112, 115, 117,
+ 120, 128, 134, 142, 148, 149, 150, 162, 163, 164,
+ 177, 185, 194, 198, 202, 206, 212, 216, 222, 226,
+ 232, 233, 235, 237, 240, 245, 249, 253, 257, 261,
+ 266, 272, 275, 276, 278, 280, 282, 284, 288, 289,
+ 291, 293, 297, 299, 301, 303, 307, 311, 313, 317,
+ 321, 323, 329, 331, 337, 339, 343, 345, 349, 351,
+ 355, 357, 361, 363, 367, 369, 373, 375, 379, 381,
+ 385, 387, 391, 393, 397, 399, 403, 405, 409, 411,
+ 415, 419, 423, 425, 429, 433, 435, 439, 441, 445,
+ 449, 451, 455, 459, 463, 465, 468, 471, 474, 477,
+ 480, 483, 486, 489, 492, 494, 497, 500, 502, 504,
+ 506, 509, 511, 513, 518, 522, 526, 529, 532, 537,
+ 541, 544, 548, 550, 554, 556, 558, 560, 562, 564,
+ 568, 571, 575, 579, 585, 588, 593, 595, 598, 599,
+ 601, 604, 608, 612, 618, 620, 622, 624, 625, 627,
+ 629, 631, 633, 635, 637, 639, 641, 643, 645, 647,
+ 649, 651, 653, 655, 657, 659
};
/* YYRHS -- A `-1'-separated list of the rules' RHS. */
static const yytype_int16 yyrhs[] =
{
- 68, 0, -1, 70, 69, -1, 34, -1, -1, -1,
- 70, 76, -1, 72, 155, 159, 75, 160, 46, 73,
- 37, -1, 36, -1, 70, -1, 38, -1, 74, 47,
- 38, -1, -1, 74, -1, 79, -1, 80, -1, 89,
- -1, 71, -1, 90, -1, 91, -1, 92, -1, 97,
- -1, 98, -1, 99, -1, 100, -1, 101, -1, 102,
- -1, 108, -1, 109, -1, 76, -1, 77, 76, -1,
- -1, 77, -1, 46, 77, 37, -1, 46, 37, -1,
- 26, 81, 158, -1, 83, -1, 81, 47, 83, -1,
- 84, -1, 82, 47, 84, -1, 38, 85, -1, 38,
- 87, -1, -1, 86, -1, 48, 118, -1, -1, 88,
- -1, 48, 119, -1, 49, -1, 114, 158, -1, 11,
- 159, 113, 160, 76, 10, 76, -1, 11, 159, 113,
- 160, 76, -1, 9, 76, 28, 159, 113, 160, 158,
- -1, 28, 159, 113, 160, 76, -1, -1, -1, 13,
- 159, 115, 93, 161, 112, 94, 161, 112, 160, 76,
- -1, -1, -1, 13, 159, 26, 82, 95, 161, 112,
- 96, 161, 112, 160, 76, -1, 13, 159, 141, 14,
- 113, 160, 76, -1, 13, 159, 26, 84, 14, 113,
- 160, 76, -1, 6, 155, 158, -1, 3, 155, 158,
- -1, 18, 112, 158, -1, 29, 159, 114, 160, 76,
- -1, 38, 50, 76, -1, 19, 159, 114, 160, 103,
- -1, 46, 104, 37, -1, 46, 104, 107, 104, 37,
- -1, -1, 105, -1, 106, -1, 105, 106, -1, 4,
- 114, 50, 78, -1, 7, 50, 78, -1, 21, 114,
- 158, -1, 24, 79, 110, -1, 24, 79, 111, -1,
- 24, 79, 110, 111, -1, 5, 159, 38, 160, 79,
- -1, 12, 79, -1, -1, 114, -1, 114, -1, 1,
- -1, 118, -1, 114, 47, 118, -1, -1, 116, -1,
- 119, -1, 116, 47, 119, -1, 39, -1, 35, -1,
- 120, -1, 141, 48, 118, -1, 141, 117, 118, -1,
- 121, -1, 141, 48, 119, -1, 141, 117, 119, -1,
- 122, -1, 122, 51, 118, 50, 118, -1, 123, -1,
- 123, 51, 119, 50, 119, -1, 124, -1, 122, 31,
- 124, -1, 125, -1, 123, 31, 125, -1, 126, -1,
- 124, 30, 126, -1, 127, -1, 125, 30, 127, -1,
- 128, -1, 126, 52, 128, -1, 129, -1, 127, 52,
- 129, -1, 130, -1, 128, 53, 130, -1, 131, -1,
- 129, 53, 131, -1, 132, -1, 130, 54, 132, -1,
- 133, -1, 131, 54, 133, -1, 134, -1, 132, 40,
- 134, -1, 135, -1, 133, 40, 135, -1, 136, -1,
- 134, 42, 136, -1, 134, 15, 136, -1, 134, 14,
- 136, -1, 136, -1, 135, 42, 136, -1, 135, 15,
- 136, -1, 137, -1, 136, 41, 137, -1, 138, -1,
- 137, 55, 138, -1, 137, 56, 138, -1, 139, -1,
- 138, 57, 139, -1, 138, 58, 139, -1, 138, 59,
- 139, -1, 140, -1, 8, 139, -1, 27, 139, -1,
- 25, 139, -1, 32, 139, -1, 33, 139, -1, 55,
- 139, -1, 56, 139, -1, 60, 139, -1, 61, 139,
- -1, 141, -1, 141, 32, -1, 141, 33, -1, 142,
- -1, 144, -1, 143, -1, 16, 142, -1, 147, -1,
- 71, -1, 143, 62, 114, 63, -1, 143, 64, 38,
- -1, 16, 143, 145, -1, 143, 145, -1, 144, 145,
- -1, 144, 62, 114, 63, -1, 144, 64, 38, -1,
- 65, 66, -1, 65, 146, 66, -1, 118, -1, 146,
- 47, 118, -1, 20, -1, 38, -1, 156, -1, 148,
- -1, 152, -1, 65, 114, 66, -1, 62, 63, -1,
- 62, 150, 63, -1, 62, 149, 63, -1, 62, 149,
- 47, 151, 63, -1, 151, 118, -1, 149, 47, 151,
- 118, -1, 47, -1, 150, 47, -1, -1, 150, -1,
- 46, 37, -1, 46, 153, 37, -1, 154, 50, 118,
- -1, 153, 47, 154, 50, 118, -1, 38, -1, 44,
- -1, 43, -1, -1, 38, -1, 17, -1, 157, -1,
- 43, -1, 44, -1, 58, -1, 35, -1, 22, -1,
- 23, -1, 49, -1, 1, -1, 65, -1, 1, -1,
- 66, -1, 1, -1, 49, -1, 1, -1
+ 70, 0, -1, 72, 71, 46, -1, 34, -1, -1,
+ -1, 72, 78, -1, 74, 157, 161, 77, 162, 48,
+ 75, 37, -1, 36, -1, 72, -1, 38, -1, 76,
+ 49, 38, -1, -1, 76, -1, 81, -1, 82, -1,
+ 91, -1, 73, -1, 92, -1, 93, -1, 94, -1,
+ 99, -1, 100, -1, 101, -1, 102, -1, 103, -1,
+ 104, -1, 110, -1, 111, -1, 78, -1, 79, 78,
+ -1, -1, 79, -1, 48, 79, 37, -1, 48, 37,
+ -1, 26, 83, 160, -1, 85, -1, 83, 49, 85,
+ -1, 86, -1, 84, 49, 86, -1, 38, 87, -1,
+ 38, 89, -1, -1, 88, -1, 50, 120, -1, -1,
+ 90, -1, 50, 121, -1, 51, -1, 116, 160, -1,
+ 11, 161, 115, 162, 78, 10, 78, -1, 11, 161,
+ 115, 162, 78, -1, 9, 78, 28, 161, 115, 162,
+ 160, -1, 28, 161, 115, 162, 78, -1, -1, -1,
+ 13, 161, 117, 95, 163, 114, 96, 163, 114, 162,
+ 78, -1, -1, -1, 13, 161, 26, 84, 97, 163,
+ 114, 98, 163, 114, 162, 78, -1, 13, 161, 143,
+ 14, 115, 162, 78, -1, 13, 161, 26, 86, 14,
+ 115, 162, 78, -1, 6, 157, 160, -1, 3, 157,
+ 160, -1, 18, 114, 160, -1, 29, 161, 116, 162,
+ 78, -1, 38, 52, 78, -1, 19, 161, 116, 162,
+ 105, -1, 48, 106, 37, -1, 48, 106, 109, 106,
+ 37, -1, -1, 107, -1, 108, -1, 107, 108, -1,
+ 4, 116, 52, 80, -1, 7, 52, 80, -1, 21,
+ 116, 160, -1, 24, 81, 112, -1, 24, 81, 113,
+ -1, 24, 81, 112, 113, -1, 5, 161, 38, 162,
+ 81, -1, 12, 81, -1, -1, 116, -1, 116, -1,
+ 1, -1, 120, -1, 116, 49, 120, -1, -1, 118,
+ -1, 121, -1, 118, 49, 121, -1, 39, -1, 35,
+ -1, 122, -1, 143, 50, 120, -1, 143, 119, 120,
+ -1, 123, -1, 143, 50, 121, -1, 143, 119, 121,
+ -1, 124, -1, 124, 53, 120, 52, 120, -1, 125,
+ -1, 125, 53, 121, 52, 121, -1, 126, -1, 124,
+ 31, 126, -1, 127, -1, 125, 31, 127, -1, 128,
+ -1, 126, 30, 128, -1, 129, -1, 127, 30, 129,
+ -1, 130, -1, 128, 54, 130, -1, 131, -1, 129,
+ 54, 131, -1, 132, -1, 130, 55, 132, -1, 133,
+ -1, 131, 55, 133, -1, 134, -1, 132, 56, 134,
+ -1, 135, -1, 133, 56, 135, -1, 136, -1, 134,
+ 40, 136, -1, 137, -1, 135, 40, 137, -1, 138,
+ -1, 136, 42, 138, -1, 136, 15, 138, -1, 136,
+ 14, 138, -1, 138, -1, 137, 42, 138, -1, 137,
+ 15, 138, -1, 139, -1, 138, 41, 139, -1, 140,
+ -1, 139, 57, 140, -1, 139, 58, 140, -1, 141,
+ -1, 140, 59, 141, -1, 140, 60, 141, -1, 140,
+ 61, 141, -1, 142, -1, 8, 141, -1, 27, 141,
+ -1, 25, 141, -1, 32, 141, -1, 33, 141, -1,
+ 57, 141, -1, 58, 141, -1, 62, 141, -1, 63,
+ 141, -1, 143, -1, 143, 32, -1, 143, 33, -1,
+ 144, -1, 146, -1, 145, -1, 16, 144, -1, 149,
+ -1, 73, -1, 145, 64, 116, 65, -1, 145, 66,
+ 38, -1, 16, 145, 147, -1, 145, 147, -1, 146,
+ 147, -1, 146, 64, 116, 65, -1, 146, 66, 38,
+ -1, 67, 68, -1, 67, 148, 68, -1, 120, -1,
+ 148, 49, 120, -1, 20, -1, 38, -1, 158, -1,
+ 150, -1, 154, -1, 67, 116, 68, -1, 64, 65,
+ -1, 64, 152, 65, -1, 64, 151, 65, -1, 64,
+ 151, 49, 153, 65, -1, 153, 120, -1, 151, 49,
+ 153, 120, -1, 49, -1, 152, 49, -1, -1, 152,
+ -1, 48, 37, -1, 48, 155, 37, -1, 156, 52,
+ 120, -1, 155, 49, 156, 52, 120, -1, 38, -1,
+ 45, -1, 43, -1, -1, 38, -1, 17, -1, 159,
+ -1, 43, -1, 45, -1, 60, -1, 35, -1, 22,
+ -1, 23, -1, 44, -1, 51, -1, 1, -1, 67,
+ -1, 1, -1, 68, -1, 1, -1, 51, -1, 1,
+ -1
};
/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
static const yytype_uint16 yyrline[] =
{
- 0, 256, 256, 260, 261, 265, 266, 271, 275, 279,
- 283, 284, 289, 290, 294, 295, 296, 297, 298, 299,
- 300, 301, 302, 303, 304, 305, 306, 307, 308, 312,
- 313, 318, 319, 323, 324, 328, 333, 334, 339, 341,
- 346, 351, 356, 357, 361, 366, 367, 371, 376, 380,
- 385, 387, 392, 394, 397, 399, 396, 403, 405, 402,
- 408, 410, 415, 420, 425, 430, 435, 440, 445, 447,
- 452, 453, 457, 458, 463, 468, 473, 478, 479, 480,
- 485, 490, 494, 495, 498, 499, 503, 504, 509, 510,
- 514, 516, 520, 521, 525, 526, 528, 533, 535, 537,
- 542, 543, 548, 550, 555, 556, 561, 563, 568, 569,
- 574, 576, 581, 582, 587, 589, 594, 595, 600, 602,
- 607, 608, 613, 615, 620, 621, 626, 627, 632, 633,
- 635, 637, 642, 643, 645, 650, 651, 656, 658, 660,
- 665, 666, 668, 670, 675, 676, 678, 679, 681, 682,
- 683, 684, 685, 686, 690, 692, 694, 700, 701, 705,
- 706, 710, 711, 712, 714, 716, 721, 723, 725, 727,
- 732, 733, 737, 738, 743, 744, 745, 746, 747, 748,
- 752, 753, 754, 755, 760, 762, 767, 768, 772, 773,
- 777, 778, 783, 785, 790, 791, 792, 796, 797, 801,
- 802, 803, 804, 805, 807, 812, 813, 816, 817, 820,
- 821, 824, 825, 828, 829
+ 0, 252, 252, 256, 257, 261, 262, 267, 271, 275,
+ 279, 280, 285, 286, 290, 291, 292, 293, 294, 295,
+ 296, 297, 298, 299, 300, 301, 302, 303, 304, 308,
+ 309, 314, 315, 319, 320, 324, 329, 330, 335, 337,
+ 342, 347, 352, 353, 357, 362, 363, 367, 372, 376,
+ 381, 383, 388, 390, 393, 395, 392, 399, 401, 398,
+ 404, 406, 411, 416, 421, 426, 431, 436, 441, 443,
+ 448, 449, 453, 454, 459, 464, 469, 474, 475, 476,
+ 481, 486, 490, 491, 494, 495, 499, 500, 505, 506,
+ 510, 512, 516, 517, 521, 522, 524, 529, 531, 533,
+ 538, 539, 544, 546, 551, 552, 557, 559, 564, 565,
+ 570, 572, 577, 578, 583, 585, 590, 591, 596, 598,
+ 603, 604, 609, 611, 616, 617, 622, 623, 628, 629,
+ 631, 633, 638, 639, 641, 646, 647, 652, 654, 656,
+ 661, 662, 664, 666, 671, 672, 674, 675, 677, 678,
+ 679, 680, 681, 682, 686, 688, 690, 696, 697, 701,
+ 702, 706, 707, 708, 710, 712, 717, 719, 721, 723,
+ 728, 729, 733, 734, 739, 740, 741, 742, 743, 744,
+ 748, 749, 750, 751, 756, 758, 763, 764, 768, 769,
+ 773, 774, 779, 781, 786, 787, 788, 792, 793, 797,
+ 798, 799, 800, 801, 803, 808, 809, 810, 813, 814,
+ 817, 818, 821, 822, 825, 826
};
#endif
"kTRUE", "kFALSE", "kTRY", "kTYPEOF", "kVAR", "kVOID", "kWHILE", "kWITH",
"tANDAND", "tOROR", "tINC", "tDEC", "tHTMLCOMMENT", "kDIVEQ",
"kFUNCTION", "'}'", "tIdentifier", "tAssignOper", "tEqOper",
- "tShiftOper", "tRelOper", "tNumericLiteral", "tStringLiteral",
- "LOWER_THAN_ELSE", "'{'", "','", "'='", "';'", "':'", "'?'", "'|'",
- "'^'", "'&'", "'+'", "'-'", "'*'", "'/'", "'%'", "'~'", "'!'", "'['",
- "']'", "'.'", "'('", "')'", "$accept", "Program", "HtmlComment",
- "SourceElements", "FunctionExpression", "KFunction", "FunctionBody",
- "FormalParameterList", "FormalParameterList_opt", "Statement",
- "StatementList", "StatementList_opt", "Block", "VariableStatement",
- "VariableDeclarationList", "VariableDeclarationListNoIn",
- "VariableDeclaration", "VariableDeclarationNoIn", "Initialiser_opt",
- "Initialiser", "InitialiserNoIn_opt", "InitialiserNoIn",
- "EmptyStatement", "ExpressionStatement", "IfStatement",
- "IterationStatement", "$@1", "$@2", "$@3", "$@4", "ContinueStatement",
- "BreakStatement", "ReturnStatement", "WithStatement",
- "LabelledStatement", "SwitchStatement", "CaseBlock", "CaseClausules_opt",
- "CaseClausules", "CaseClausule", "DefaultClausule", "ThrowStatement",
- "TryStatement", "Catch", "Finally", "Expression_opt", "Expression_err",
- "Expression", "ExpressionNoIn_opt", "ExpressionNoIn", "AssignOper",
- "AssignmentExpression", "AssignmentExpressionNoIn",
+ "tShiftOper", "tRelOper", "tNumericLiteral", "tBooleanLiteral",
+ "tStringLiteral", "tEOF", "LOWER_THAN_ELSE", "'{'", "','", "'='", "';'",
+ "':'", "'?'", "'|'", "'^'", "'&'", "'+'", "'-'", "'*'", "'/'", "'%'",
+ "'~'", "'!'", "'['", "']'", "'.'", "'('", "')'", "$accept", "Program",
+ "HtmlComment", "SourceElements", "FunctionExpression", "KFunction",
+ "FunctionBody", "FormalParameterList", "FormalParameterList_opt",
+ "Statement", "StatementList", "StatementList_opt", "Block",
+ "VariableStatement", "VariableDeclarationList",
+ "VariableDeclarationListNoIn", "VariableDeclaration",
+ "VariableDeclarationNoIn", "Initialiser_opt", "Initialiser",
+ "InitialiserNoIn_opt", "InitialiserNoIn", "EmptyStatement",
+ "ExpressionStatement", "IfStatement", "IterationStatement", "$@1", "$@2",
+ "$@3", "$@4", "ContinueStatement", "BreakStatement", "ReturnStatement",
+ "WithStatement", "LabelledStatement", "SwitchStatement", "CaseBlock",
+ "CaseClausules_opt", "CaseClausules", "CaseClausule", "DefaultClausule",
+ "ThrowStatement", "TryStatement", "Catch", "Finally", "Expression_opt",
+ "Expression_err", "Expression", "ExpressionNoIn_opt", "ExpressionNoIn",
+ "AssignOper", "AssignmentExpression", "AssignmentExpressionNoIn",
"ConditionalExpression", "ConditionalExpressionNoIn",
"LogicalORExpression", "LogicalORExpressionNoIn", "LogicalANDExpression",
"LogicalANDExpressionNoIn", "BitwiseORExpression",
265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
275, 276, 277, 278, 279, 280, 281, 282, 283, 284,
285, 286, 287, 288, 289, 290, 291, 125, 292, 293,
- 294, 295, 296, 297, 298, 299, 123, 44, 61, 59,
- 58, 63, 124, 94, 38, 43, 45, 42, 47, 37,
- 126, 33, 91, 93, 46, 40, 41
+ 294, 295, 296, 297, 298, 299, 300, 301, 123, 44,
+ 61, 59, 58, 63, 124, 94, 38, 43, 45, 42,
+ 47, 37, 126, 33, 91, 93, 46, 40, 41
};
# endif
/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
static const yytype_uint8 yyr1[] =
{
- 0, 67, 68, 69, 69, 70, 70, 71, 72, 73,
- 74, 74, 75, 75, 76, 76, 76, 76, 76, 76,
- 76, 76, 76, 76, 76, 76, 76, 76, 76, 77,
- 77, 78, 78, 79, 79, 80, 81, 81, 82, 82,
- 83, 84, 85, 85, 86, 87, 87, 88, 89, 90,
- 91, 91, 92, 92, 93, 94, 92, 95, 96, 92,
- 92, 92, 97, 98, 99, 100, 101, 102, 103, 103,
- 104, 104, 105, 105, 106, 107, 108, 109, 109, 109,
- 110, 111, 112, 112, 113, 113, 114, 114, 115, 115,
- 116, 116, 117, 117, 118, 118, 118, 119, 119, 119,
- 120, 120, 121, 121, 122, 122, 123, 123, 124, 124,
- 125, 125, 126, 126, 127, 127, 128, 128, 129, 129,
- 130, 130, 131, 131, 132, 132, 133, 133, 134, 134,
- 134, 134, 135, 135, 135, 136, 136, 137, 137, 137,
- 138, 138, 138, 138, 139, 139, 139, 139, 139, 139,
- 139, 139, 139, 139, 140, 140, 140, 141, 141, 142,
- 142, 143, 143, 143, 143, 143, 144, 144, 144, 144,
- 145, 145, 146, 146, 147, 147, 147, 147, 147, 147,
- 148, 148, 148, 148, 149, 149, 150, 150, 151, 151,
- 152, 152, 153, 153, 154, 154, 154, 155, 155, 156,
- 156, 156, 156, 156, 156, 157, 157, 158, 158, 159,
- 159, 160, 160, 161, 161
+ 0, 69, 70, 71, 71, 72, 72, 73, 74, 75,
+ 76, 76, 77, 77, 78, 78, 78, 78, 78, 78,
+ 78, 78, 78, 78, 78, 78, 78, 78, 78, 79,
+ 79, 80, 80, 81, 81, 82, 83, 83, 84, 84,
+ 85, 86, 87, 87, 88, 89, 89, 90, 91, 92,
+ 93, 93, 94, 94, 95, 96, 94, 97, 98, 94,
+ 94, 94, 99, 100, 101, 102, 103, 104, 105, 105,
+ 106, 106, 107, 107, 108, 109, 110, 111, 111, 111,
+ 112, 113, 114, 114, 115, 115, 116, 116, 117, 117,
+ 118, 118, 119, 119, 120, 120, 120, 121, 121, 121,
+ 122, 122, 123, 123, 124, 124, 125, 125, 126, 126,
+ 127, 127, 128, 128, 129, 129, 130, 130, 131, 131,
+ 132, 132, 133, 133, 134, 134, 135, 135, 136, 136,
+ 136, 136, 137, 137, 137, 138, 138, 139, 139, 139,
+ 140, 140, 140, 140, 141, 141, 141, 141, 141, 141,
+ 141, 141, 141, 141, 142, 142, 142, 143, 143, 144,
+ 144, 145, 145, 145, 145, 145, 146, 146, 146, 146,
+ 147, 147, 148, 148, 149, 149, 149, 149, 149, 149,
+ 150, 150, 150, 150, 151, 151, 152, 152, 153, 153,
+ 154, 154, 155, 155, 156, 156, 156, 157, 157, 158,
+ 158, 158, 158, 158, 158, 159, 159, 159, 160, 160,
+ 161, 161, 162, 162, 163, 163
};
/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
static const yytype_uint8 yyr2[] =
{
- 0, 2, 2, 1, 0, 0, 2, 8, 1, 1,
+ 0, 2, 3, 1, 0, 0, 2, 8, 1, 1,
1, 3, 0, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2, 0, 1, 3, 2, 3, 1, 3, 1, 3,
2, 3, 3, 5, 2, 4, 1, 2, 0, 1,
2, 3, 3, 5, 1, 1, 1, 0, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1
+ 1, 1, 1, 1, 1, 1
};
/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
5, 0, 4, 1, 197, 197, 0, 0, 0, 0,
0, 199, 82, 0, 174, 0, 205, 206, 0, 0,
0, 0, 0, 0, 0, 0, 3, 204, 8, 175,
- 201, 202, 0, 48, 0, 0, 203, 0, 0, 188,
- 0, 2, 17, 197, 6, 14, 15, 16, 18, 19,
- 20, 21, 22, 23, 24, 25, 26, 27, 28, 0,
- 86, 94, 100, 104, 108, 112, 116, 120, 124, 128,
- 135, 137, 140, 144, 154, 157, 159, 158, 161, 177,
- 178, 176, 200, 198, 0, 0, 175, 0, 162, 145,
- 154, 0, 210, 209, 0, 88, 160, 159, 0, 83,
- 0, 0, 0, 0, 147, 42, 0, 36, 146, 0,
- 0, 148, 149, 0, 34, 175, 201, 202, 29, 0,
- 0, 0, 150, 151, 152, 153, 186, 180, 0, 189,
- 0, 0, 0, 208, 0, 207, 49, 0, 0, 0,
+ 201, 207, 202, 0, 48, 0, 0, 203, 0, 0,
+ 188, 0, 0, 17, 197, 6, 14, 15, 16, 18,
+ 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
+ 0, 86, 94, 100, 104, 108, 112, 116, 120, 124,
+ 128, 135, 137, 140, 144, 154, 157, 159, 158, 161,
+ 177, 178, 176, 200, 198, 0, 0, 175, 0, 162,
+ 145, 154, 0, 211, 210, 0, 88, 160, 159, 0,
+ 83, 0, 0, 0, 0, 147, 42, 0, 36, 146,
+ 0, 0, 148, 149, 0, 34, 175, 201, 202, 29,
+ 0, 0, 0, 150, 151, 152, 153, 186, 180, 0,
+ 189, 0, 0, 2, 0, 209, 0, 208, 49, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 155, 156, 93, 92, 0,
+ 0, 0, 0, 0, 166, 0, 0, 167, 63, 62,
+ 190, 194, 196, 195, 0, 85, 0, 84, 0, 54,
+ 89, 90, 97, 102, 106, 110, 114, 118, 122, 126,
+ 132, 154, 165, 64, 0, 76, 34, 0, 0, 77,
+ 78, 0, 40, 43, 0, 35, 0, 0, 66, 33,
+ 30, 191, 0, 0, 188, 182, 187, 181, 184, 179,
+ 12, 87, 105, 0, 109, 113, 117, 121, 125, 131,
+ 130, 129, 136, 138, 139, 141, 142, 143, 95, 96,
+ 0, 164, 170, 172, 0, 0, 169, 0, 213, 212,
+ 0, 45, 57, 38, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 155, 156, 93, 92, 0, 0, 0,
- 0, 0, 166, 0, 0, 167, 63, 62, 190, 194,
- 196, 195, 0, 85, 0, 84, 0, 54, 89, 90,
- 97, 102, 106, 110, 114, 118, 122, 126, 132, 154,
- 165, 64, 0, 76, 34, 0, 0, 77, 78, 0,
- 40, 43, 0, 35, 0, 0, 66, 33, 30, 191,
- 0, 0, 188, 182, 187, 181, 184, 179, 12, 87,
- 105, 0, 109, 113, 117, 121, 125, 131, 130, 129,
- 136, 138, 139, 141, 142, 143, 95, 96, 0, 164,
- 170, 172, 0, 0, 169, 0, 212, 211, 0, 45,
- 57, 38, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 81, 79,
- 44, 37, 0, 0, 0, 192, 189, 0, 10, 13,
- 0, 0, 163, 0, 171, 168, 0, 51, 0, 41,
- 46, 0, 0, 0, 214, 213, 82, 91, 154, 107,
- 0, 111, 115, 119, 123, 127, 134, 133, 0, 98,
- 99, 70, 67, 0, 53, 65, 0, 183, 185, 0,
- 0, 101, 173, 0, 0, 47, 39, 82, 0, 55,
- 0, 0, 0, 0, 71, 72, 0, 193, 11, 5,
- 52, 50, 58, 0, 0, 103, 60, 0, 0, 68,
- 70, 73, 80, 9, 0, 0, 61, 82, 31, 31,
- 0, 7, 82, 0, 32, 74, 75, 69, 0, 0,
- 0, 56, 59
+ 81, 79, 44, 37, 0, 0, 0, 192, 189, 0,
+ 10, 13, 0, 0, 163, 0, 171, 168, 0, 51,
+ 0, 41, 46, 0, 0, 0, 215, 214, 82, 91,
+ 154, 107, 0, 111, 115, 119, 123, 127, 134, 133,
+ 0, 98, 99, 70, 67, 0, 53, 65, 0, 183,
+ 185, 0, 0, 101, 173, 0, 0, 47, 39, 82,
+ 0, 55, 0, 0, 0, 0, 71, 72, 0, 193,
+ 11, 5, 52, 50, 58, 0, 0, 103, 60, 0,
+ 0, 68, 70, 73, 80, 9, 0, 0, 61, 82,
+ 31, 31, 0, 7, 82, 0, 32, 74, 75, 69,
+ 0, 0, 0, 56, 59
};
/* YYDEFGOTO[NTERM-NUM]. */
static const yytype_int16 yydefgoto[] =
{
- -1, 1, 41, 2, 88, 43, 354, 279, 280, 118,
- 119, 365, 45, 46, 106, 250, 107, 251, 200, 201,
- 289, 290, 47, 48, 49, 50, 252, 344, 292, 355,
- 51, 52, 53, 54, 55, 56, 312, 333, 334, 335,
- 350, 57, 58, 197, 198, 98, 174, 59, 177, 178,
- 265, 60, 179, 61, 180, 62, 181, 63, 182, 64,
- 183, 65, 184, 66, 185, 67, 186, 68, 187, 69,
- 70, 71, 72, 73, 74, 75, 76, 77, 162, 242,
- 78, 79, 128, 129, 130, 80, 120, 121, 84, 81,
- 82, 136, 94, 248, 296
+ -1, 1, 42, 2, 89, 44, 356, 281, 282, 119,
+ 120, 367, 46, 47, 107, 252, 108, 253, 202, 203,
+ 291, 292, 48, 49, 50, 51, 254, 346, 294, 357,
+ 52, 53, 54, 55, 56, 57, 314, 335, 336, 337,
+ 352, 58, 59, 199, 200, 99, 176, 60, 179, 180,
+ 267, 61, 181, 62, 182, 63, 183, 64, 184, 65,
+ 185, 66, 186, 67, 187, 68, 188, 69, 189, 70,
+ 71, 72, 73, 74, 75, 76, 77, 78, 164, 244,
+ 79, 80, 129, 130, 131, 81, 121, 122, 85, 82,
+ 83, 138, 95, 250, 298
};
/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
STATE-NUM. */
-#define YYPACT_NINF -287
+#define YYPACT_NINF -293
static const yytype_int16 yypact[] =
{
- -287, 29, 490, -287, -18, -18, 934, 730, 21, 21,
- 965, -287, 934, 21, -287, 934, -287, -287, 36, 934,
- 89, 934, 21, 21, 934, 934, -287, -287, -287, 105,
- -287, -287, 550, -287, 934, 934, -287, 934, 934, 61,
- 934, -287, 403, -18, -287, -287, -287, -287, -287, -287,
- -287, -287, -287, -287, -287, -287, -287, -287, -287, 15,
- -287, -287, 41, 106, 117, 129, 142, 158, 76, 162,
- 131, 47, -287, -287, 141, -287, 113, 148, -287, -287,
- -287, -287, -287, -287, 5, 5, -287, 147, -287, -287,
- 169, 177, -287, -287, 370, 832, -287, 113, 5, 164,
- 934, 15, 610, 123, -287, 159, 16, -287, -287, 370,
- 934, -287, -287, 730, 438, 105, 175, 176, -287, 670,
- 86, 178, -287, -287, -287, -287, -287, -287, 62, 63,
- 934, 28, 21, -287, 934, -287, -287, 934, 934, 934,
- 934, 934, 934, 934, 934, 934, 934, 934, 934, 934,
- 934, 934, 934, -287, -287, -287, -287, 934, 934, 934,
- 181, 781, -287, 934, 189, -287, -287, -287, -287, -287,
- -287, -287, 21, -287, 8, 164, 191, -287, 183, -287,
- -287, 56, 201, 180, 182, 179, 194, 53, 162, 10,
- -287, -287, 12, -287, -287, 21, 36, 225, -287, 934,
- -287, -287, 89, -287, 8, 12, -287, -287, -287, -287,
- 94, 934, 193, -287, -287, -287, -287, -287, 200, -287,
- 106, 192, 117, 129, 142, 158, 76, 162, 162, 162,
- 131, 47, 47, -287, -287, -287, -287, -287, 68, -287,
- -287, -287, 46, 109, -287, 370, -287, -287, 730, 195,
- 197, 227, 18, 934, 934, 934, 934, 934, 934, 934,
- 934, 934, 934, 370, 934, 934, 199, 209, -287, -287,
- -287, -287, 730, 730, 202, -287, 204, 883, -287, 206,
- 8, 934, -287, 934, -287, -287, 8, 239, 934, -287,
- -287, 191, 18, 370, -287, -287, 934, -287, 160, 201,
- 218, 180, 182, 179, 194, 53, 162, 162, 8, -287,
- -287, 250, -287, 8, -287, -287, 934, -287, -287, 231,
- 228, -287, -287, 5, 730, -287, -287, 934, 8, -287,
- 934, 730, 934, 66, 250, -287, 36, -287, -287, -287,
- -287, -287, -287, 730, 18, -287, -287, -32, 226, -287,
- 250, -287, -287, 730, 238, 18, -287, 934, 730, 730,
- 240, -287, 934, 8, 730, -287, -287, -287, 8, 730,
- 730, -287, -287
+ -293, 53, 496, -293, 26, 26, 956, 744, 8, 8,
+ 986, -293, 956, 8, -293, 956, -293, -293, 39, 956,
+ 71, 956, 8, 8, 956, 956, -293, -293, -293, 67,
+ -293, -293, -293, 558, -293, 956, 956, -293, 956, 956,
+ 41, 956, 76, 410, 26, -293, -293, -293, -293, -293,
+ -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
+ 19, -293, -293, -7, 102, 100, 108, 111, 135, 36,
+ 142, -43, 97, -293, -293, 129, -293, 105, 118, -293,
+ -293, -293, -293, -293, -293, 7, 7, -293, 176, -293,
+ -293, 49, 158, -293, -293, 372, 850, -293, 105, 7,
+ 140, 956, 19, 620, 125, -293, 153, 47, -293, -293,
+ 372, 956, -293, -293, 744, 442, 67, 155, 163, -293,
+ 682, 80, 165, -293, -293, -293, -293, -293, -293, 42,
+ 48, 956, 31, -293, 8, -293, 956, -293, -293, 956,
+ 956, 956, 956, 956, 956, 956, 956, 956, 956, 956,
+ 956, 956, 956, 956, 956, -293, -293, -293, -293, 956,
+ 956, 956, 180, 797, -293, 956, 182, -293, -293, -293,
+ -293, -293, -293, -293, 8, -293, 3, 140, 184, -293,
+ 181, -293, -293, 35, 195, 172, 178, 175, 192, 23,
+ 142, 120, -293, -293, 11, -293, -293, 8, 39, 222,
+ -293, 956, -293, -293, 71, -293, 3, 11, -293, -293,
+ -293, -293, 90, 956, 186, -293, -293, -293, -293, -293,
+ 198, -293, 102, 185, 100, 108, 111, 135, 36, 142,
+ 142, 142, -43, 97, 97, -293, -293, -293, -293, -293,
+ 56, -293, -293, -293, 34, 66, -293, 372, -293, -293,
+ 744, 188, 190, 226, 10, 956, 956, 956, 956, 956,
+ 956, 956, 956, 956, 956, 372, 956, 956, 193, 204,
+ -293, -293, -293, -293, 744, 744, 194, -293, 196, 903,
+ -293, 202, 3, 956, -293, 956, -293, -293, 3, 234,
+ 956, -293, -293, 184, 10, 372, -293, -293, 956, -293,
+ 177, 195, 214, 172, 178, 175, 192, 23, 142, 142,
+ 3, -293, -293, 263, -293, 3, -293, -293, 956, -293,
+ -293, 230, 221, -293, -293, 7, 744, -293, -293, 956,
+ 3, -293, 956, 744, 956, 6, 263, -293, 39, -293,
+ -293, -293, -293, -293, -293, 744, 10, -293, -293, 59,
+ 219, -293, 263, -293, -293, 744, 239, 10, -293, 956,
+ 744, 744, 240, -293, 956, 3, 744, -293, -293, -293,
+ 3, 744, 744, -293, -293
};
/* YYPGOTO[NTERM-NUM]. */
static const yytype_int16 yypgoto[] =
{
- -287, -287, -287, -61, -2, -287, -287, -287, -287, 0,
- -141, -80, -15, -287, -287, -287, 78, -10, -287, -287,
- -287, -287, -287, -287, -287, -287, -287, -287, -287, -287,
- -287, -287, -287, -287, -287, -287, -287, -68, -287, -50,
- -287, -287, -287, -287, 88, -286, -105, 20, -287, -287,
- 212, -77, -209, -287, -287, -287, -287, 150, 34, 152,
- 33, 153, 35, 154, 38, 156, 40, 151, 42, -94,
- 157, 75, 64, -287, 2, 290, 291, -287, 19, -287,
- -287, -287, -287, 93, 95, -287, -287, 96, 26, -287,
- -287, -73, 25, 17, -278
+ -293, -293, -293, -63, -2, -293, -293, -293, -293, 0,
+ -187, -82, -17, -293, -293, -293, 77, -10, -293, -293,
+ -293, -293, -293, -293, -293, -293, -293, -293, -293, -293,
+ -293, -293, -293, -293, -293, -293, -293, -68, -293, -51,
+ -293, -293, -293, -293, 87, -292, -87, 15, -293, -293,
+ 213, -36, -238, -293, -293, -293, -293, 150, 40, 149,
+ 33, 151, 43, 152, 44, 148, 45, 156, 46, -62,
+ 145, 37, 38, -293, -3, 287, 288, -293, -9, -293,
+ -293, -293, -293, 86, 89, -293, -293, 95, 5, -293,
+ -293, -60, 32, 17, -254
};
/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
#define YYTABLE_NINF -197
static const yytype_int16 yytable[] =
{
- 42, 188, 44, 103, 204, 42, 133, 91, 90, 246,
- 329, 166, 167, 246, 327, 134, 133, 133, 358, 294,
- 83, 90, 92, 90, 263, 191, 90, 90, 193, 3,
- 42, 85, 99, 203, 95, 101, 90, 90, 100, 90,
- 90, 342, 153, 154, 297, 155, 300, 109, 110, 156,
- 227, 228, 229, 216, 135, 309, 310, 219, 264, 134,
- 131, 221, 134, 202, 135, 135, 357, 295, 261, 132,
- 89, 363, 137, 348, 247, 134, 368, 362, 247, 325,
- 236, 237, 102, 104, 241, 108, 93, 254, 111, 112,
- 144, 145, 138, 283, 217, 262, 165, 189, 122, 123,
- 42, 124, 125, 349, 150, 151, 152, 255, 126, 212,
- 214, 42, 284, 206, 175, 134, 190, 42, 146, 208,
- 192, 345, 270, 209, 127, 213, 215, 105, 195, 175,
- 205, 282, 169, 210, 275, 196, 139, 170, 171, 90,
- 286, 90, 90, 90, 90, 90, 90, 90, 90, 90,
- 90, 90, 90, 90, 90, 113, 134, 218, 308, 188,
- 188, 188, 188, 188, 188, 188, 188, 306, 307, 140,
- 188, 188, 285, 153, 154, 159, 155, 160, 161, 238,
- 156, 268, 141, 243, 168, 169, 148, 149, 328, 157,
- 170, 171, 153, 154, 188, 155, 142, 245, 143, 156,
- 318, 153, 154, 147, 321, 172, 322, 199, 264, 266,
- 163, 134, 164, 161, 233, 234, 235, 364, 364, 239,
- 267, 272, 273, 231, 232, -196, -195, 244, 211, 249,
- 253, 256, 257, 259, 260, 258, 188, 196, 278, 337,
- 126, 293, 281, 288, 291, 311, 42, 313, 287, 324,
- 340, 214, 316, 319, 332, 298, 90, 298, 90, 90,
- 90, 90, 90, 90, 90, 175, 298, 298, 330, 338,
- 42, 42, 314, 315, 339, 361, 359, 367, 353, 366,
- 271, 326, 360, 175, 351, 269, 158, 220, 299, 301,
- 298, 222, 302, 223, 226, 224, 303, 320, 225, 304,
- 96, 97, 305, 323, 230, 276, 274, 277, 0, 0,
- 0, 0, 0, 175, 0, 0, 99, 0, 0, 0,
- 0, 352, 42, 0, 341, 331, 0, 0, 0, 42,
- 336, 346, 298, 0, 0, 0, 0, 0, 0, 0,
- 0, 42, 0, 356, 0, 343, 0, 99, 0, 0,
- 0, 42, 347, 44, 0, 0, 42, 42, 0, 0,
- 0, 0, 42, 0, 208, 0, 0, 42, 42, 371,
- 372, 173, 0, 0, 0, 0, 0, 99, 6, 0,
- 369, 0, 99, 0, 0, 370, 10, 11, 0, 0,
- 14, 0, 16, 17, 0, 19, 0, 21, 0, 0,
- 0, 0, 24, 25, -162, 27, 28, 0, 86, 0,
- 0, 0, 0, 30, 31, 0, 87, -162, -162, 0,
- 0, 0, 0, 0, 0, 34, 35, 0, 36, 0,
- 37, 38, 39, -162, -162, 40, 0, 0, 0, -190,
- 0, 0, -162, -162, -162, -162, 0, 0, 0, 0,
- -162, -162, -190, -190, -162, -162, -162, -162, 0, 0,
- -162, 0, -162, 0, 0, 0, 0, -162, -190, -190,
- 0, 0, 0, 0, 0, 0, 0, -190, -190, -190,
- -190, 0, 0, 0, 0, -190, -190, 0, 0, -190,
- -190, -190, -190, 4, 0, -190, 5, -190, 6, 7,
- 0, 8, -190, 9, 0, 0, 10, 11, 12, 13,
- 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
- 0, 0, 24, 25, 26, 27, 28, 0, 29, 0,
- 0, 0, 0, 30, 31, 0, 32, 0, 0, 33,
- 0, 0, 0, 0, 0, 34, 35, 0, 36, 0,
- 37, 38, 39, 4, 0, 40, 5, 0, 6, 7,
- 0, 8, 0, 9, 0, 0, 10, 11, 12, 13,
- 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
- 0, 0, 24, 25, 0, 27, 28, 114, 115, 0,
- 0, 0, 0, 116, 117, 0, 32, 0, 0, 33,
- 0, 0, 0, 0, 0, 34, 35, 0, 36, 0,
- 37, 38, 39, 4, 0, 40, 5, 0, 6, 7,
- 0, 8, 0, 9, 0, 0, 10, 11, 12, 13,
- 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
- 0, 0, 24, 25, 0, 27, 28, 194, 29, 0,
- 0, 0, 0, 30, 31, 0, 32, 0, 0, 33,
- 0, 0, 0, 0, 0, 34, 35, 0, 36, 0,
- 37, 38, 39, 4, 0, 40, 5, 0, 6, 7,
- 0, 8, 0, 9, 0, 0, 10, 11, 12, 13,
- 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
- 0, 0, 24, 25, 0, 27, 28, 207, 29, 0,
- 0, 0, 0, 30, 31, 0, 32, 0, 0, 33,
- 0, 0, 0, 0, 0, 34, 35, 0, 36, 0,
- 37, 38, 39, 4, 0, 40, 5, 0, 6, 7,
+ 43, 104, 45, 91, 248, 43, 331, 92, 135, 93,
+ 86, 296, 248, 350, 150, 151, 91, 299, 91, 302,
+ 135, 91, 91, 206, 139, 168, 169, 100, 311, 312,
+ 102, 43, 91, 91, 190, 91, 91, 344, 263, 193,
+ 329, 96, 195, 351, 90, 101, 140, 205, 135, 134,
+ 146, 147, 327, 3, 110, 111, 132, 105, 137, 109,
+ 136, 297, 112, 113, 84, 264, 256, 365, 136, 167,
+ 137, 249, 370, 123, 124, 94, 125, 126, 148, 249,
+ 136, 155, 156, 285, 229, 230, 231, 103, 257, 192,
+ 127, 214, 359, 191, 347, 218, 204, 216, 137, 219,
+ 221, 43, 286, 364, 223, 136, 128, 215, 136, 106,
+ 177, 360, 43, 217, 208, 136, 194, 211, 43, 114,
+ 210, 284, 133, 238, 239, 177, 207, 243, 171, 212,
+ 197, 287, 141, 172, 265, 173, 91, 198, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 155, 156, 142, 157, 152, 153, 154, 158,
+ 288, 155, 156, 143, 157, 272, 220, 144, 158, 161,
+ 266, 162, 163, 366, 366, 145, 240, 277, 310, 159,
+ 245, 270, 165, 149, 166, 163, 174, 233, 234, 136,
+ 235, 236, 237, 190, 190, 190, 190, 190, 190, 190,
+ 190, 308, 309, 201, 190, 190, 247, -196, 330, 155,
+ 156, 268, 157, 170, 171, -195, 158, 213, 241, 172,
+ 246, 173, 251, 274, 275, 258, 259, 266, 190, 269,
+ 255, 261, 262, 260, 198, 127, 280, 283, 290, 293,
+ 295, 313, 315, 320, 326, 216, 318, 323, 43, 324,
+ 289, 321, 300, 91, 300, 91, 91, 91, 91, 91,
+ 91, 91, 177, 300, 300, 342, 332, 334, 340, 341,
+ 190, 361, 43, 43, 316, 317, 363, 369, 355, 368,
+ 177, 273, 339, 328, 362, 353, 271, 300, 160, 222,
+ 224, 303, 227, 225, 232, 226, 301, 97, 98, 322,
+ 278, 228, 304, 279, 305, 325, 306, 276, 307, 0,
+ 177, 0, 0, 100, 0, 0, 0, 0, 0, 0,
+ 0, 354, 0, 0, 43, 0, 343, 333, 0, 300,
+ 0, 43, 338, 348, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 43, 100, 358, 0, 345, 0, 349,
+ 0, 0, 0, 43, 0, 45, 0, 0, 43, 43,
+ 0, 0, 0, 0, 43, 0, 210, 0, 0, 43,
+ 43, 373, 374, 175, 100, 0, 0, 0, 0, 100,
+ 6, 0, 371, 0, 0, 0, 0, 372, 10, 11,
+ 0, 0, 14, 0, 16, 17, 0, 19, 0, 21,
+ 0, 0, 0, 0, 24, 25, 0, 27, 28, 0,
+ 87, -162, 0, 0, 0, 30, 31, 32, 0, 0,
+ 88, 0, 0, 0, -162, -162, 0, 0, 0, 35,
+ 36, 0, 37, 0, 38, 39, 40, 0, 0, 41,
+ -162, -162, 0, -190, 0, 0, 0, 0, 0, -162,
+ -162, -162, -162, 0, 0, 0, -190, -190, 0, -162,
+ -162, 0, 0, -162, -162, -162, -162, 0, 0, -162,
+ 0, -162, -190, -190, 0, 0, -162, 0, 0, 0,
+ 0, -190, -190, -190, -190, 0, 0, 0, 0, 0,
+ 0, -190, -190, 0, 0, -190, -190, -190, -190, 4,
+ 0, -190, 5, -190, 6, 7, 0, 8, -190, 9,
+ 0, 0, 10, 11, 12, 13, 14, 15, 16, 17,
+ 18, 19, 20, 21, 22, 23, 0, 0, 24, 25,
+ 26, 27, 28, 0, 29, 0, 0, 0, 0, 30,
+ 31, 32, 0, 0, 33, 0, 0, 34, 0, 0,
+ 0, 0, 0, 35, 36, 0, 37, 0, 38, 39,
+ 40, 4, 0, 41, 5, 0, 6, 7, 0, 8,
+ 0, 9, 0, 0, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 0, 0,
+ 24, 25, 0, 27, 28, 115, 116, 0, 0, 0,
+ 0, 117, 31, 118, 0, 0, 33, 0, 0, 34,
+ 0, 0, 0, 0, 0, 35, 36, 0, 37, 0,
+ 38, 39, 40, 4, 0, 41, 5, 0, 6, 7,
0, 8, 0, 9, 0, 0, 10, 11, 12, 13,
14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
- 0, 0, 24, 25, 0, 27, 28, 0, 29, 0,
- 0, 0, 0, 30, 31, 0, 32, 0, 0, 33,
- 0, 0, 0, 0, 0, 34, 35, 0, 36, 6,
- 37, 38, 39, 0, 0, 40, 0, 10, 11, 0,
- 0, 14, 0, 16, 17, 0, 19, 0, 21, 0,
- 0, 0, 0, 24, 25, 0, 27, 28, 0, 86,
- 0, 0, 0, 0, 30, 31, 0, 87, 0, 0,
- 0, 0, 0, 0, 0, 0, 34, 35, 0, 36,
- 6, 37, 38, 39, 0, 0, 40, 240, 10, 11,
- 0, 0, 14, 0, 16, 17, 0, 19, 176, 21,
- 0, 0, 0, 0, 24, 25, 0, 27, 28, 0,
- 86, 0, 0, 0, 0, 30, 31, 0, 87, 0,
- 0, 0, 0, 0, 0, 0, 0, 34, 35, 0,
- 36, 6, 37, 38, 39, 0, 0, 40, 0, 10,
+ 0, 0, 24, 25, 0, 27, 28, 196, 29, 0,
+ 0, 0, 0, 30, 31, 32, 0, 0, 33, 0,
+ 0, 34, 0, 0, 0, 0, 0, 35, 36, 0,
+ 37, 0, 38, 39, 40, 4, 0, 41, 5, 0,
+ 6, 7, 0, 8, 0, 9, 0, 0, 10, 11,
+ 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 0, 0, 24, 25, 0, 27, 28, 209,
+ 29, 0, 0, 0, 0, 30, 31, 32, 0, 0,
+ 33, 0, 0, 34, 0, 0, 0, 0, 0, 35,
+ 36, 0, 37, 0, 38, 39, 40, 4, 0, 41,
+ 5, 0, 6, 7, 0, 8, 0, 9, 0, 0,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 0, 0, 24, 25, 0, 27,
+ 28, 0, 29, 0, 0, 0, 0, 30, 31, 32,
+ 0, 0, 33, 0, 0, 34, 0, 0, 0, 0,
+ 0, 35, 36, 0, 37, 6, 38, 39, 40, 0,
+ 0, 41, 0, 10, 11, 0, 0, 14, 0, 16,
+ 17, 0, 19, 0, 21, 0, 0, 0, 0, 24,
+ 25, 0, 27, 28, 0, 87, 0, 0, 0, 0,
+ 30, 31, 32, 0, 0, 88, 0, 0, 0, 0,
+ 0, 0, 0, 0, 35, 36, 0, 37, 6, 38,
+ 39, 40, 0, 0, 41, 242, 10, 11, 0, 0,
+ 14, 0, 16, 17, 0, 19, 178, 21, 0, 0,
+ 0, 0, 24, 25, 0, 27, 28, 0, 87, 0,
+ 0, 0, 0, 30, 31, 32, 0, 0, 88, 0,
+ 0, 0, 0, 0, 0, 0, 0, 35, 36, 0,
+ 37, 6, 38, 39, 40, 0, 0, 41, 0, 10,
11, 0, 0, 14, 0, 16, 17, 0, 19, 0,
21, 0, 0, 0, 0, 24, 25, 0, 27, 28,
- 0, 86, 0, 0, 0, 0, 30, 31, 0, 87,
- 0, 0, 0, 0, 0, 0, 0, 0, 34, 35,
- 0, 36, 6, 37, 38, 39, 317, 0, 40, 0,
- 10, 11, 0, 0, 14, 0, 16, 17, 0, 19,
- 0, 21, 0, 0, 0, 0, 24, 25, 0, 27,
- 28, 0, 86, 0, 0, 0, 0, 30, 31, 0,
- 87, 10, 11, 0, 0, 14, 0, 16, 17, 34,
- 35, 0, 36, 0, 37, 38, 39, 0, 0, 40,
- 27, 28, 0, 86, 0, 0, 0, 0, 30, 31,
- 0, 87, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 36, 0, 0, 0, 39, 0, 0,
- 40
+ 0, 87, 0, 0, 0, 0, 30, 31, 32, 0,
+ 0, 88, 0, 0, 0, 0, 0, 0, 0, 0,
+ 35, 36, 0, 37, 6, 38, 39, 40, 319, 0,
+ 41, 0, 10, 11, 0, 0, 14, 0, 16, 17,
+ 0, 19, 0, 21, 0, 0, 0, 0, 24, 25,
+ 0, 27, 28, 0, 87, 0, 0, 0, 0, 30,
+ 31, 32, 10, 11, 88, 0, 14, 0, 16, 17,
+ 0, 0, 0, 35, 36, 0, 37, 0, 38, 39,
+ 40, 27, 28, 41, 87, 0, 0, 0, 0, 30,
+ 31, 32, 0, 0, 88, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 37, 0, 0, 0,
+ 40, 0, 0, 41
};
static const yytype_int16 yycheck[] =
{
- 2, 95, 2, 18, 109, 7, 1, 7, 6, 1,
- 296, 84, 85, 1, 292, 47, 1, 1, 50, 1,
- 38, 19, 1, 21, 14, 98, 24, 25, 101, 0,
- 32, 5, 12, 106, 9, 15, 34, 35, 13, 37,
- 38, 327, 32, 33, 253, 35, 255, 22, 23, 39,
- 144, 145, 146, 130, 49, 264, 265, 134, 48, 47,
- 40, 138, 47, 47, 49, 49, 344, 49, 15, 43,
- 6, 357, 31, 7, 66, 47, 362, 355, 66, 288,
- 157, 158, 46, 19, 161, 21, 65, 31, 24, 25,
- 14, 15, 51, 47, 66, 42, 77, 95, 34, 35,
- 102, 37, 38, 37, 57, 58, 59, 51, 47, 47,
- 47, 113, 66, 113, 94, 47, 97, 119, 42, 119,
- 100, 330, 199, 37, 63, 63, 63, 38, 5, 109,
- 110, 63, 38, 47, 211, 12, 30, 43, 44, 137,
- 245, 139, 140, 141, 142, 143, 144, 145, 146, 147,
- 148, 149, 150, 151, 152, 50, 47, 132, 263, 253,
- 254, 255, 256, 257, 258, 259, 260, 261, 262, 52,
- 264, 265, 63, 32, 33, 62, 35, 64, 65, 159,
- 39, 196, 53, 163, 37, 38, 55, 56, 293, 48,
- 43, 44, 32, 33, 288, 35, 54, 172, 40, 39,
- 277, 32, 33, 41, 281, 28, 283, 48, 48, 192,
- 62, 47, 64, 65, 150, 151, 152, 358, 359, 38,
- 195, 204, 205, 148, 149, 50, 50, 38, 50, 38,
- 47, 30, 52, 54, 40, 53, 330, 12, 38, 316,
- 47, 14, 50, 48, 47, 46, 248, 38, 248, 10,
- 323, 47, 50, 47, 4, 253, 254, 255, 256, 257,
- 258, 259, 260, 261, 262, 245, 264, 265, 50, 38,
- 272, 273, 272, 273, 46, 37, 50, 37, 339, 359,
- 202, 291, 350, 263, 334, 197, 74, 137, 254, 256,
- 288, 139, 257, 140, 143, 141, 258, 280, 142, 259,
- 10, 10, 260, 286, 147, 212, 210, 212, -1, -1,
- -1, -1, -1, 293, -1, -1, 296, -1, -1, -1,
- -1, 336, 324, -1, 324, 308, -1, -1, -1, 331,
- 313, 331, 330, -1, -1, -1, -1, -1, -1, -1,
- -1, 343, -1, 343, -1, 328, -1, 327, -1, -1,
- -1, 353, 332, 353, -1, -1, 358, 359, -1, -1,
- -1, -1, 364, -1, 364, -1, -1, 369, 370, 369,
- 370, 1, -1, -1, -1, -1, -1, 357, 8, -1,
- 363, -1, 362, -1, -1, 368, 16, 17, -1, -1,
- 20, -1, 22, 23, -1, 25, -1, 27, -1, -1,
- -1, -1, 32, 33, 1, 35, 36, -1, 38, -1,
- -1, -1, -1, 43, 44, -1, 46, 14, 15, -1,
- -1, -1, -1, -1, -1, 55, 56, -1, 58, -1,
- 60, 61, 62, 30, 31, 65, -1, -1, -1, 1,
- -1, -1, 39, 40, 41, 42, -1, -1, -1, -1,
- 47, 48, 14, 15, 51, 52, 53, 54, -1, -1,
- 57, -1, 59, -1, -1, -1, -1, 64, 30, 31,
- -1, -1, -1, -1, -1, -1, -1, 39, 40, 41,
- 42, -1, -1, -1, -1, 47, 48, -1, -1, 51,
- 52, 53, 54, 3, -1, 57, 6, 59, 8, 9,
- -1, 11, 64, 13, -1, -1, 16, 17, 18, 19,
- 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
- -1, -1, 32, 33, 34, 35, 36, -1, 38, -1,
- -1, -1, -1, 43, 44, -1, 46, -1, -1, 49,
- -1, -1, -1, -1, -1, 55, 56, -1, 58, -1,
- 60, 61, 62, 3, -1, 65, 6, -1, 8, 9,
- -1, 11, -1, 13, -1, -1, 16, 17, 18, 19,
- 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
- -1, -1, 32, 33, -1, 35, 36, 37, 38, -1,
- -1, -1, -1, 43, 44, -1, 46, -1, -1, 49,
- -1, -1, -1, -1, -1, 55, 56, -1, 58, -1,
- 60, 61, 62, 3, -1, 65, 6, -1, 8, 9,
- -1, 11, -1, 13, -1, -1, 16, 17, 18, 19,
- 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
- -1, -1, 32, 33, -1, 35, 36, 37, 38, -1,
- -1, -1, -1, 43, 44, -1, 46, -1, -1, 49,
- -1, -1, -1, -1, -1, 55, 56, -1, 58, -1,
- 60, 61, 62, 3, -1, 65, 6, -1, 8, 9,
+ 2, 18, 2, 6, 1, 7, 298, 7, 1, 1,
+ 5, 1, 1, 7, 57, 58, 19, 255, 21, 257,
+ 1, 24, 25, 110, 31, 85, 86, 12, 266, 267,
+ 15, 33, 35, 36, 96, 38, 39, 329, 15, 99,
+ 294, 9, 102, 37, 6, 13, 53, 107, 1, 44,
+ 14, 15, 290, 0, 22, 23, 41, 19, 51, 21,
+ 49, 51, 24, 25, 38, 42, 31, 359, 49, 78,
+ 51, 68, 364, 35, 36, 67, 38, 39, 42, 68,
+ 49, 32, 33, 49, 146, 147, 148, 48, 53, 98,
+ 49, 49, 346, 96, 332, 131, 49, 49, 51, 68,
+ 136, 103, 68, 357, 140, 49, 65, 65, 49, 38,
+ 95, 52, 114, 65, 114, 49, 101, 37, 120, 52,
+ 120, 65, 46, 159, 160, 110, 111, 163, 38, 49,
+ 5, 65, 30, 43, 14, 45, 139, 12, 141, 142,
+ 143, 144, 145, 146, 147, 148, 149, 150, 151, 152,
+ 153, 154, 32, 33, 54, 35, 59, 60, 61, 39,
+ 247, 32, 33, 55, 35, 201, 134, 56, 39, 64,
+ 50, 66, 67, 360, 361, 40, 161, 213, 265, 50,
+ 165, 198, 64, 41, 66, 67, 28, 150, 151, 49,
+ 152, 153, 154, 255, 256, 257, 258, 259, 260, 261,
+ 262, 263, 264, 50, 266, 267, 174, 52, 295, 32,
+ 33, 194, 35, 37, 38, 52, 39, 52, 38, 43,
+ 38, 45, 38, 206, 207, 30, 54, 50, 290, 197,
+ 49, 56, 40, 55, 12, 49, 38, 52, 50, 49,
+ 14, 48, 38, 279, 10, 49, 52, 283, 250, 285,
+ 250, 49, 255, 256, 257, 258, 259, 260, 261, 262,
+ 263, 264, 247, 266, 267, 325, 52, 4, 38, 48,
+ 332, 52, 274, 275, 274, 275, 37, 37, 341, 361,
+ 265, 204, 318, 293, 352, 336, 199, 290, 75, 139,
+ 141, 258, 144, 142, 149, 143, 256, 10, 10, 282,
+ 214, 145, 259, 214, 260, 288, 261, 212, 262, -1,
+ 295, -1, -1, 298, -1, -1, -1, -1, -1, -1,
+ -1, 338, -1, -1, 326, -1, 326, 310, -1, 332,
+ -1, 333, 315, 333, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 345, 329, 345, -1, 330, -1, 334,
+ -1, -1, -1, 355, -1, 355, -1, -1, 360, 361,
+ -1, -1, -1, -1, 366, -1, 366, -1, -1, 371,
+ 372, 371, 372, 1, 359, -1, -1, -1, -1, 364,
+ 8, -1, 365, -1, -1, -1, -1, 370, 16, 17,
+ -1, -1, 20, -1, 22, 23, -1, 25, -1, 27,
+ -1, -1, -1, -1, 32, 33, -1, 35, 36, -1,
+ 38, 1, -1, -1, -1, 43, 44, 45, -1, -1,
+ 48, -1, -1, -1, 14, 15, -1, -1, -1, 57,
+ 58, -1, 60, -1, 62, 63, 64, -1, -1, 67,
+ 30, 31, -1, 1, -1, -1, -1, -1, -1, 39,
+ 40, 41, 42, -1, -1, -1, 14, 15, -1, 49,
+ 50, -1, -1, 53, 54, 55, 56, -1, -1, 59,
+ -1, 61, 30, 31, -1, -1, 66, -1, -1, -1,
+ -1, 39, 40, 41, 42, -1, -1, -1, -1, -1,
+ -1, 49, 50, -1, -1, 53, 54, 55, 56, 3,
+ -1, 59, 6, 61, 8, 9, -1, 11, 66, 13,
+ -1, -1, 16, 17, 18, 19, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, -1, -1, 32, 33,
+ 34, 35, 36, -1, 38, -1, -1, -1, -1, 43,
+ 44, 45, -1, -1, 48, -1, -1, 51, -1, -1,
+ -1, -1, -1, 57, 58, -1, 60, -1, 62, 63,
+ 64, 3, -1, 67, 6, -1, 8, 9, -1, 11,
+ -1, 13, -1, -1, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, -1, -1,
+ 32, 33, -1, 35, 36, 37, 38, -1, -1, -1,
+ -1, 43, 44, 45, -1, -1, 48, -1, -1, 51,
+ -1, -1, -1, -1, -1, 57, 58, -1, 60, -1,
+ 62, 63, 64, 3, -1, 67, 6, -1, 8, 9,
-1, 11, -1, 13, -1, -1, 16, 17, 18, 19,
20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
-1, -1, 32, 33, -1, 35, 36, 37, 38, -1,
- -1, -1, -1, 43, 44, -1, 46, -1, -1, 49,
- -1, -1, -1, -1, -1, 55, 56, -1, 58, -1,
- 60, 61, 62, 3, -1, 65, 6, -1, 8, 9,
- -1, 11, -1, 13, -1, -1, 16, 17, 18, 19,
- 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ -1, -1, -1, 43, 44, 45, -1, -1, 48, -1,
+ -1, 51, -1, -1, -1, -1, -1, 57, 58, -1,
+ 60, -1, 62, 63, 64, 3, -1, 67, 6, -1,
+ 8, 9, -1, 11, -1, 13, -1, -1, 16, 17,
+ 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
+ 28, 29, -1, -1, 32, 33, -1, 35, 36, 37,
+ 38, -1, -1, -1, -1, 43, 44, 45, -1, -1,
+ 48, -1, -1, 51, -1, -1, -1, -1, -1, 57,
+ 58, -1, 60, -1, 62, 63, 64, 3, -1, 67,
+ 6, -1, 8, 9, -1, 11, -1, 13, -1, -1,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
+ 26, 27, 28, 29, -1, -1, 32, 33, -1, 35,
+ 36, -1, 38, -1, -1, -1, -1, 43, 44, 45,
+ -1, -1, 48, -1, -1, 51, -1, -1, -1, -1,
+ -1, 57, 58, -1, 60, 8, 62, 63, 64, -1,
+ -1, 67, -1, 16, 17, -1, -1, 20, -1, 22,
+ 23, -1, 25, -1, 27, -1, -1, -1, -1, 32,
+ 33, -1, 35, 36, -1, 38, -1, -1, -1, -1,
+ 43, 44, 45, -1, -1, 48, -1, -1, -1, -1,
+ -1, -1, -1, -1, 57, 58, -1, 60, 8, 62,
+ 63, 64, -1, -1, 67, 68, 16, 17, -1, -1,
+ 20, -1, 22, 23, -1, 25, 26, 27, -1, -1,
-1, -1, 32, 33, -1, 35, 36, -1, 38, -1,
- -1, -1, -1, 43, 44, -1, 46, -1, -1, 49,
- -1, -1, -1, -1, -1, 55, 56, -1, 58, 8,
- 60, 61, 62, -1, -1, 65, -1, 16, 17, -1,
- -1, 20, -1, 22, 23, -1, 25, -1, 27, -1,
- -1, -1, -1, 32, 33, -1, 35, 36, -1, 38,
- -1, -1, -1, -1, 43, 44, -1, 46, -1, -1,
- -1, -1, -1, -1, -1, -1, 55, 56, -1, 58,
- 8, 60, 61, 62, -1, -1, 65, 66, 16, 17,
- -1, -1, 20, -1, 22, 23, -1, 25, 26, 27,
- -1, -1, -1, -1, 32, 33, -1, 35, 36, -1,
- 38, -1, -1, -1, -1, 43, 44, -1, 46, -1,
- -1, -1, -1, -1, -1, -1, -1, 55, 56, -1,
- 58, 8, 60, 61, 62, -1, -1, 65, -1, 16,
+ -1, -1, -1, 43, 44, 45, -1, -1, 48, -1,
+ -1, -1, -1, -1, -1, -1, -1, 57, 58, -1,
+ 60, 8, 62, 63, 64, -1, -1, 67, -1, 16,
17, -1, -1, 20, -1, 22, 23, -1, 25, -1,
27, -1, -1, -1, -1, 32, 33, -1, 35, 36,
- -1, 38, -1, -1, -1, -1, 43, 44, -1, 46,
- -1, -1, -1, -1, -1, -1, -1, -1, 55, 56,
- -1, 58, 8, 60, 61, 62, 63, -1, 65, -1,
- 16, 17, -1, -1, 20, -1, 22, 23, -1, 25,
- -1, 27, -1, -1, -1, -1, 32, 33, -1, 35,
- 36, -1, 38, -1, -1, -1, -1, 43, 44, -1,
- 46, 16, 17, -1, -1, 20, -1, 22, 23, 55,
- 56, -1, 58, -1, 60, 61, 62, -1, -1, 65,
- 35, 36, -1, 38, -1, -1, -1, -1, 43, 44,
- -1, 46, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 58, -1, -1, -1, 62, -1, -1,
- 65
+ -1, 38, -1, -1, -1, -1, 43, 44, 45, -1,
+ -1, 48, -1, -1, -1, -1, -1, -1, -1, -1,
+ 57, 58, -1, 60, 8, 62, 63, 64, 65, -1,
+ 67, -1, 16, 17, -1, -1, 20, -1, 22, 23,
+ -1, 25, -1, 27, -1, -1, -1, -1, 32, 33,
+ -1, 35, 36, -1, 38, -1, -1, -1, -1, 43,
+ 44, 45, 16, 17, 48, -1, 20, -1, 22, 23,
+ -1, -1, -1, 57, 58, -1, 60, -1, 62, 63,
+ 64, 35, 36, 67, 38, -1, -1, -1, -1, 43,
+ 44, 45, -1, -1, 48, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 60, -1, -1, -1,
+ 64, -1, -1, 67
};
/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
symbol of state STATE-NUM. */
static const yytype_uint8 yystos[] =
{
- 0, 68, 70, 0, 3, 6, 8, 9, 11, 13,
+ 0, 70, 72, 0, 3, 6, 8, 9, 11, 13,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
26, 27, 28, 29, 32, 33, 34, 35, 36, 38,
- 43, 44, 46, 49, 55, 56, 58, 60, 61, 62,
- 65, 69, 71, 72, 76, 79, 80, 89, 90, 91,
- 92, 97, 98, 99, 100, 101, 102, 108, 109, 114,
- 118, 120, 122, 124, 126, 128, 130, 132, 134, 136,
- 137, 138, 139, 140, 141, 142, 143, 144, 147, 148,
- 152, 156, 157, 38, 155, 155, 38, 46, 71, 139,
- 141, 76, 1, 65, 159, 159, 142, 143, 112, 114,
- 159, 114, 46, 79, 139, 38, 81, 83, 139, 159,
- 159, 139, 139, 50, 37, 38, 43, 44, 76, 77,
- 153, 154, 139, 139, 139, 139, 47, 63, 149, 150,
- 151, 114, 155, 1, 47, 49, 158, 31, 51, 30,
- 52, 53, 54, 40, 14, 15, 42, 41, 55, 56,
- 57, 58, 59, 32, 33, 35, 39, 48, 117, 62,
- 64, 65, 145, 62, 64, 145, 158, 158, 37, 38,
- 43, 44, 28, 1, 113, 114, 26, 115, 116, 119,
- 121, 123, 125, 127, 129, 131, 133, 135, 136, 141,
- 145, 158, 114, 158, 37, 5, 12, 110, 111, 48,
- 85, 86, 47, 158, 113, 114, 76, 37, 76, 37,
- 47, 50, 47, 63, 47, 63, 118, 66, 159, 118,
- 124, 118, 126, 128, 130, 132, 134, 136, 136, 136,
- 137, 138, 138, 139, 139, 139, 118, 118, 114, 38,
- 66, 118, 146, 114, 38, 159, 1, 66, 160, 38,
- 82, 84, 93, 47, 31, 51, 30, 52, 53, 54,
- 40, 15, 42, 14, 48, 117, 160, 159, 79, 111,
- 118, 83, 160, 160, 154, 118, 150, 151, 38, 74,
- 75, 50, 63, 47, 66, 63, 113, 76, 48, 87,
- 88, 47, 95, 14, 1, 49, 161, 119, 141, 125,
- 119, 127, 129, 131, 133, 135, 136, 136, 113, 119,
- 119, 46, 103, 38, 76, 76, 50, 63, 118, 47,
- 160, 118, 118, 160, 10, 119, 84, 161, 113, 112,
- 50, 160, 4, 104, 105, 106, 160, 118, 38, 46,
- 158, 76, 112, 160, 94, 119, 76, 114, 7, 37,
- 107, 106, 79, 70, 73, 96, 76, 161, 50, 50,
- 104, 37, 161, 112, 77, 78, 78, 37, 112, 160,
- 160, 76, 76
+ 43, 44, 45, 48, 51, 57, 58, 60, 62, 63,
+ 64, 67, 71, 73, 74, 78, 81, 82, 91, 92,
+ 93, 94, 99, 100, 101, 102, 103, 104, 110, 111,
+ 116, 120, 122, 124, 126, 128, 130, 132, 134, 136,
+ 138, 139, 140, 141, 142, 143, 144, 145, 146, 149,
+ 150, 154, 158, 159, 38, 157, 157, 38, 48, 73,
+ 141, 143, 78, 1, 67, 161, 161, 144, 145, 114,
+ 116, 161, 116, 48, 81, 141, 38, 83, 85, 141,
+ 161, 161, 141, 141, 52, 37, 38, 43, 45, 78,
+ 79, 155, 156, 141, 141, 141, 141, 49, 65, 151,
+ 152, 153, 116, 46, 157, 1, 49, 51, 160, 31,
+ 53, 30, 54, 55, 56, 40, 14, 15, 42, 41,
+ 57, 58, 59, 60, 61, 32, 33, 35, 39, 50,
+ 119, 64, 66, 67, 147, 64, 66, 147, 160, 160,
+ 37, 38, 43, 45, 28, 1, 115, 116, 26, 117,
+ 118, 121, 123, 125, 127, 129, 131, 133, 135, 137,
+ 138, 143, 147, 160, 116, 160, 37, 5, 12, 112,
+ 113, 50, 87, 88, 49, 160, 115, 116, 78, 37,
+ 78, 37, 49, 52, 49, 65, 49, 65, 120, 68,
+ 161, 120, 126, 120, 128, 130, 132, 134, 136, 138,
+ 138, 138, 139, 140, 140, 141, 141, 141, 120, 120,
+ 116, 38, 68, 120, 148, 116, 38, 161, 1, 68,
+ 162, 38, 84, 86, 95, 49, 31, 53, 30, 54,
+ 55, 56, 40, 15, 42, 14, 50, 119, 162, 161,
+ 81, 113, 120, 85, 162, 162, 156, 120, 152, 153,
+ 38, 76, 77, 52, 65, 49, 68, 65, 115, 78,
+ 50, 89, 90, 49, 97, 14, 1, 51, 163, 121,
+ 143, 127, 121, 129, 131, 133, 135, 137, 138, 138,
+ 115, 121, 121, 48, 105, 38, 78, 78, 52, 65,
+ 120, 49, 162, 120, 120, 162, 10, 121, 86, 163,
+ 115, 114, 52, 162, 4, 106, 107, 108, 162, 120,
+ 38, 48, 160, 78, 114, 162, 96, 121, 78, 116,
+ 7, 37, 109, 108, 81, 72, 75, 98, 78, 163,
+ 52, 52, 106, 37, 163, 114, 79, 80, 80, 37,
+ 114, 162, 162, 78, 78
};
#define yyerrok (yyerrstatus = 0)
case 2:
/* Line 1455 of yacc.c */
-#line 257 "parser.y"
- { program_parsed(ctx, (yyvsp[(1) - (2)].source_elements)); ;}
+#line 253 "parser.y"
+ { program_parsed(ctx, (yyvsp[(1) - (3)].source_elements)); ;}
break;
case 3:
/* Line 1455 of yacc.c */
-#line 260 "parser.y"
+#line 256 "parser.y"
{;}
break;
case 4:
/* Line 1455 of yacc.c */
-#line 261 "parser.y"
+#line 257 "parser.y"
{;}
break;
case 5:
/* Line 1455 of yacc.c */
-#line 265 "parser.y"
+#line 261 "parser.y"
{ (yyval.source_elements) = new_source_elements(ctx); ;}
break;
case 6:
/* Line 1455 of yacc.c */
-#line 267 "parser.y"
+#line 263 "parser.y"
{ (yyval.source_elements) = source_elements_add_statement((yyvsp[(1) - (2)].source_elements), (yyvsp[(2) - (2)].statement)); ;}
break;
case 7:
/* Line 1455 of yacc.c */
-#line 272 "parser.y"
+#line 268 "parser.y"
{ (yyval.expr) = new_function_expression(ctx, (yyvsp[(2) - (8)].identifier), (yyvsp[(4) - (8)].parameter_list), (yyvsp[(7) - (8)].source_elements), (yyvsp[(1) - (8)].srcptr), (yyvsp[(8) - (8)].srcptr)-(yyvsp[(1) - (8)].srcptr)+1); ;}
break;
case 8:
/* Line 1455 of yacc.c */
-#line 275 "parser.y"
- { push_func(ctx); (yyval.srcptr) = (yyvsp[(1) - (1)].srcptr); ;}
+#line 271 "parser.y"
+ { (yyval.srcptr) = (yyvsp[(1) - (1)].srcptr); ;}
break;
case 9:
/* Line 1455 of yacc.c */
-#line 279 "parser.y"
- { (yyval.source_elements) = function_body_parsed(ctx, (yyvsp[(1) - (1)].source_elements)); ;}
+#line 275 "parser.y"
+ { (yyval.source_elements) = (yyvsp[(1) - (1)].source_elements); ;}
break;
case 10:
/* Line 1455 of yacc.c */
-#line 283 "parser.y"
+#line 279 "parser.y"
{ (yyval.parameter_list) = new_parameter_list(ctx, (yyvsp[(1) - (1)].identifier)); ;}
break;
case 11:
/* Line 1455 of yacc.c */
-#line 285 "parser.y"
+#line 281 "parser.y"
{ (yyval.parameter_list) = parameter_list_add(ctx, (yyvsp[(1) - (3)].parameter_list), (yyvsp[(3) - (3)].identifier)); ;}
break;
case 12:
/* Line 1455 of yacc.c */
-#line 289 "parser.y"
+#line 285 "parser.y"
{ (yyval.parameter_list) = NULL; ;}
break;
case 13:
/* Line 1455 of yacc.c */
-#line 290 "parser.y"
+#line 286 "parser.y"
{ (yyval.parameter_list) = (yyvsp[(1) - (1)].parameter_list); ;}
break;
case 14:
/* Line 1455 of yacc.c */
-#line 294 "parser.y"
+#line 290 "parser.y"
{ (yyval.statement) = (yyvsp[(1) - (1)].statement); ;}
break;
case 15:
/* Line 1455 of yacc.c */
-#line 295 "parser.y"
+#line 291 "parser.y"
{ (yyval.statement) = (yyvsp[(1) - (1)].statement); ;}
break;
case 16:
/* Line 1455 of yacc.c */
-#line 296 "parser.y"
+#line 292 "parser.y"
{ (yyval.statement) = (yyvsp[(1) - (1)].statement); ;}
break;
case 17:
/* Line 1455 of yacc.c */
-#line 297 "parser.y"
- { (yyval.statement) = new_empty_statement(ctx); ;}
+#line 293 "parser.y"
+ { (yyval.statement) = new_expression_statement(ctx, (yyvsp[(1) - (1)].expr)); ;}
break;
case 18:
/* Line 1455 of yacc.c */
-#line 298 "parser.y"
+#line 294 "parser.y"
{ (yyval.statement) = (yyvsp[(1) - (1)].statement); ;}
break;
case 19:
/* Line 1455 of yacc.c */
-#line 299 "parser.y"
+#line 295 "parser.y"
{ (yyval.statement) = (yyvsp[(1) - (1)].statement); ;}
break;
case 20:
/* Line 1455 of yacc.c */
-#line 300 "parser.y"
+#line 296 "parser.y"
{ (yyval.statement) = (yyvsp[(1) - (1)].statement); ;}
break;
case 21:
/* Line 1455 of yacc.c */
-#line 301 "parser.y"
+#line 297 "parser.y"
{ (yyval.statement) = (yyvsp[(1) - (1)].statement); ;}
break;
case 22:
/* Line 1455 of yacc.c */
-#line 302 "parser.y"
+#line 298 "parser.y"
{ (yyval.statement) = (yyvsp[(1) - (1)].statement); ;}
break;
case 23:
/* Line 1455 of yacc.c */
-#line 303 "parser.y"
+#line 299 "parser.y"
{ (yyval.statement) = (yyvsp[(1) - (1)].statement); ;}
break;
case 24:
/* Line 1455 of yacc.c */
-#line 304 "parser.y"
+#line 300 "parser.y"
{ (yyval.statement) = (yyvsp[(1) - (1)].statement); ;}
break;
case 25:
/* Line 1455 of yacc.c */
-#line 305 "parser.y"
+#line 301 "parser.y"
{ (yyval.statement) = (yyvsp[(1) - (1)].statement); ;}
break;
case 26:
/* Line 1455 of yacc.c */
-#line 306 "parser.y"
+#line 302 "parser.y"
{ (yyval.statement) = (yyvsp[(1) - (1)].statement); ;}
break;
case 27:
/* Line 1455 of yacc.c */
-#line 307 "parser.y"
+#line 303 "parser.y"
{ (yyval.statement) = (yyvsp[(1) - (1)].statement); ;}
break;
case 28:
/* Line 1455 of yacc.c */
-#line 308 "parser.y"
+#line 304 "parser.y"
{ (yyval.statement) = (yyvsp[(1) - (1)].statement); ;}
break;
case 29:
/* Line 1455 of yacc.c */
-#line 312 "parser.y"
+#line 308 "parser.y"
{ (yyval.statement_list) = new_statement_list(ctx, (yyvsp[(1) - (1)].statement)); ;}
break;
case 30:
/* Line 1455 of yacc.c */
-#line 314 "parser.y"
+#line 310 "parser.y"
{ (yyval.statement_list) = statement_list_add((yyvsp[(1) - (2)].statement_list), (yyvsp[(2) - (2)].statement)); ;}
break;
case 31:
/* Line 1455 of yacc.c */
-#line 318 "parser.y"
+#line 314 "parser.y"
{ (yyval.statement_list) = NULL; ;}
break;
case 32:
/* Line 1455 of yacc.c */
-#line 319 "parser.y"
+#line 315 "parser.y"
{ (yyval.statement_list) = (yyvsp[(1) - (1)].statement_list); ;}
break;
case 33:
/* Line 1455 of yacc.c */
-#line 323 "parser.y"
+#line 319 "parser.y"
{ (yyval.statement) = new_block_statement(ctx, (yyvsp[(2) - (3)].statement_list)); ;}
break;
case 34:
/* Line 1455 of yacc.c */
-#line 324 "parser.y"
+#line 320 "parser.y"
{ (yyval.statement) = new_block_statement(ctx, NULL); ;}
break;
case 35:
/* Line 1455 of yacc.c */
-#line 329 "parser.y"
+#line 325 "parser.y"
{ (yyval.statement) = new_var_statement(ctx, (yyvsp[(2) - (3)].variable_list)); ;}
break;
case 36:
/* Line 1455 of yacc.c */
-#line 333 "parser.y"
+#line 329 "parser.y"
{ (yyval.variable_list) = new_variable_list(ctx, (yyvsp[(1) - (1)].variable_declaration)); ;}
break;
case 37:
/* Line 1455 of yacc.c */
-#line 335 "parser.y"
+#line 331 "parser.y"
{ (yyval.variable_list) = variable_list_add(ctx, (yyvsp[(1) - (3)].variable_list), (yyvsp[(3) - (3)].variable_declaration)); ;}
break;
case 38:
/* Line 1455 of yacc.c */
-#line 340 "parser.y"
+#line 336 "parser.y"
{ (yyval.variable_list) = new_variable_list(ctx, (yyvsp[(1) - (1)].variable_declaration)); ;}
break;
case 39:
/* Line 1455 of yacc.c */
-#line 342 "parser.y"
+#line 338 "parser.y"
{ (yyval.variable_list) = variable_list_add(ctx, (yyvsp[(1) - (3)].variable_list), (yyvsp[(3) - (3)].variable_declaration)); ;}
break;
case 40:
/* Line 1455 of yacc.c */
-#line 347 "parser.y"
+#line 343 "parser.y"
{ (yyval.variable_declaration) = new_variable_declaration(ctx, (yyvsp[(1) - (2)].identifier), (yyvsp[(2) - (2)].expr)); ;}
break;
case 41:
/* Line 1455 of yacc.c */
-#line 352 "parser.y"
+#line 348 "parser.y"
{ (yyval.variable_declaration) = new_variable_declaration(ctx, (yyvsp[(1) - (2)].identifier), (yyvsp[(2) - (2)].expr)); ;}
break;
case 42:
/* Line 1455 of yacc.c */
-#line 356 "parser.y"
+#line 352 "parser.y"
{ (yyval.expr) = NULL; ;}
break;
case 43:
/* Line 1455 of yacc.c */
-#line 357 "parser.y"
+#line 353 "parser.y"
{ (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
break;
case 44:
/* Line 1455 of yacc.c */
-#line 362 "parser.y"
+#line 358 "parser.y"
{ (yyval.expr) = (yyvsp[(2) - (2)].expr); ;}
break;
case 45:
/* Line 1455 of yacc.c */
-#line 366 "parser.y"
+#line 362 "parser.y"
{ (yyval.expr) = NULL; ;}
break;
case 46:
/* Line 1455 of yacc.c */
-#line 367 "parser.y"
+#line 363 "parser.y"
{ (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
break;
case 47:
/* Line 1455 of yacc.c */
-#line 372 "parser.y"
+#line 368 "parser.y"
{ (yyval.expr) = (yyvsp[(2) - (2)].expr); ;}
break;
case 48:
/* Line 1455 of yacc.c */
-#line 376 "parser.y"
- { (yyval.statement) = new_empty_statement(ctx); ;}
+#line 372 "parser.y"
+ { (yyval.statement) = new_statement(ctx, STAT_EMPTY, 0); ;}
break;
case 49:
/* Line 1455 of yacc.c */
-#line 381 "parser.y"
+#line 377 "parser.y"
{ (yyval.statement) = new_expression_statement(ctx, (yyvsp[(1) - (2)].expr)); ;}
break;
case 50:
/* Line 1455 of yacc.c */
-#line 386 "parser.y"
+#line 382 "parser.y"
{ (yyval.statement) = new_if_statement(ctx, (yyvsp[(3) - (7)].expr), (yyvsp[(5) - (7)].statement), (yyvsp[(7) - (7)].statement)); ;}
break;
case 51:
/* Line 1455 of yacc.c */
-#line 388 "parser.y"
+#line 384 "parser.y"
{ (yyval.statement) = new_if_statement(ctx, (yyvsp[(3) - (5)].expr), (yyvsp[(5) - (5)].statement), NULL); ;}
break;
case 52:
/* Line 1455 of yacc.c */
-#line 393 "parser.y"
+#line 389 "parser.y"
{ (yyval.statement) = new_while_statement(ctx, TRUE, (yyvsp[(5) - (7)].expr), (yyvsp[(2) - (7)].statement)); ;}
break;
case 53:
/* Line 1455 of yacc.c */
-#line 395 "parser.y"
+#line 391 "parser.y"
{ (yyval.statement) = new_while_statement(ctx, FALSE, (yyvsp[(3) - (5)].expr), (yyvsp[(5) - (5)].statement)); ;}
break;
case 54:
/* Line 1455 of yacc.c */
-#line 397 "parser.y"
+#line 393 "parser.y"
{ if(!explicit_error(ctx, (yyvsp[(3) - (3)].expr), ';')) YYABORT; ;}
break;
case 55:
/* Line 1455 of yacc.c */
-#line 399 "parser.y"
+#line 395 "parser.y"
{ if(!explicit_error(ctx, (yyvsp[(6) - (6)].expr), ';')) YYABORT; ;}
break;
case 56:
/* Line 1455 of yacc.c */
-#line 401 "parser.y"
+#line 397 "parser.y"
{ (yyval.statement) = new_for_statement(ctx, NULL, (yyvsp[(3) - (11)].expr), (yyvsp[(6) - (11)].expr), (yyvsp[(9) - (11)].expr), (yyvsp[(11) - (11)].statement)); ;}
break;
case 57:
/* Line 1455 of yacc.c */
-#line 403 "parser.y"
+#line 399 "parser.y"
{ if(!explicit_error(ctx, (yyvsp[(4) - (4)].variable_list), ';')) YYABORT; ;}
break;
case 58:
/* Line 1455 of yacc.c */
-#line 405 "parser.y"
+#line 401 "parser.y"
{ if(!explicit_error(ctx, (yyvsp[(7) - (7)].expr), ';')) YYABORT; ;}
break;
case 59:
/* Line 1455 of yacc.c */
-#line 407 "parser.y"
+#line 403 "parser.y"
{ (yyval.statement) = new_for_statement(ctx, (yyvsp[(4) - (12)].variable_list), NULL, (yyvsp[(7) - (12)].expr), (yyvsp[(10) - (12)].expr), (yyvsp[(12) - (12)].statement)); ;}
break;
case 60:
/* Line 1455 of yacc.c */
-#line 409 "parser.y"
+#line 405 "parser.y"
{ (yyval.statement) = new_forin_statement(ctx, NULL, (yyvsp[(3) - (7)].expr), (yyvsp[(5) - (7)].expr), (yyvsp[(7) - (7)].statement)); ;}
break;
case 61:
/* Line 1455 of yacc.c */
-#line 411 "parser.y"
+#line 407 "parser.y"
{ (yyval.statement) = new_forin_statement(ctx, (yyvsp[(4) - (8)].variable_declaration), NULL, (yyvsp[(6) - (8)].expr), (yyvsp[(8) - (8)].statement)); ;}
break;
case 62:
/* Line 1455 of yacc.c */
-#line 416 "parser.y"
+#line 412 "parser.y"
{ (yyval.statement) = new_continue_statement(ctx, (yyvsp[(2) - (3)].identifier)); ;}
break;
case 63:
/* Line 1455 of yacc.c */
-#line 421 "parser.y"
+#line 417 "parser.y"
{ (yyval.statement) = new_break_statement(ctx, (yyvsp[(2) - (3)].identifier)); ;}
break;
case 64:
/* Line 1455 of yacc.c */
-#line 426 "parser.y"
+#line 422 "parser.y"
{ (yyval.statement) = new_return_statement(ctx, (yyvsp[(2) - (3)].expr)); ;}
break;
case 65:
/* Line 1455 of yacc.c */
-#line 431 "parser.y"
+#line 427 "parser.y"
{ (yyval.statement) = new_with_statement(ctx, (yyvsp[(3) - (5)].expr), (yyvsp[(5) - (5)].statement)); ;}
break;
case 66:
/* Line 1455 of yacc.c */
-#line 436 "parser.y"
+#line 432 "parser.y"
{ (yyval.statement) = new_labelled_statement(ctx, (yyvsp[(1) - (3)].identifier), (yyvsp[(3) - (3)].statement)); ;}
break;
case 67:
/* Line 1455 of yacc.c */
-#line 441 "parser.y"
+#line 437 "parser.y"
{ (yyval.statement) = new_switch_statement(ctx, (yyvsp[(3) - (5)].expr), (yyvsp[(5) - (5)].case_clausule)); ;}
break;
case 68:
/* Line 1455 of yacc.c */
-#line 446 "parser.y"
+#line 442 "parser.y"
{ (yyval.case_clausule) = new_case_block(ctx, (yyvsp[(2) - (3)].case_list), NULL, NULL); ;}
break;
case 69:
/* Line 1455 of yacc.c */
-#line 448 "parser.y"
+#line 444 "parser.y"
{ (yyval.case_clausule) = new_case_block(ctx, (yyvsp[(2) - (5)].case_list), (yyvsp[(3) - (5)].case_clausule), (yyvsp[(4) - (5)].case_list)); ;}
break;
case 70:
/* Line 1455 of yacc.c */
-#line 452 "parser.y"
+#line 448 "parser.y"
{ (yyval.case_list) = NULL; ;}
break;
case 71:
/* Line 1455 of yacc.c */
-#line 453 "parser.y"
+#line 449 "parser.y"
{ (yyval.case_list) = (yyvsp[(1) - (1)].case_list); ;}
break;
case 72:
/* Line 1455 of yacc.c */
-#line 457 "parser.y"
+#line 453 "parser.y"
{ (yyval.case_list) = new_case_list(ctx, (yyvsp[(1) - (1)].case_clausule)); ;}
break;
case 73:
/* Line 1455 of yacc.c */
-#line 459 "parser.y"
+#line 455 "parser.y"
{ (yyval.case_list) = case_list_add(ctx, (yyvsp[(1) - (2)].case_list), (yyvsp[(2) - (2)].case_clausule)); ;}
break;
case 74:
/* Line 1455 of yacc.c */
-#line 464 "parser.y"
+#line 460 "parser.y"
{ (yyval.case_clausule) = new_case_clausule(ctx, (yyvsp[(2) - (4)].expr), (yyvsp[(4) - (4)].statement_list)); ;}
break;
case 75:
/* Line 1455 of yacc.c */
-#line 469 "parser.y"
+#line 465 "parser.y"
{ (yyval.case_clausule) = new_case_clausule(ctx, NULL, (yyvsp[(3) - (3)].statement_list)); ;}
break;
case 76:
/* Line 1455 of yacc.c */
-#line 474 "parser.y"
+#line 470 "parser.y"
{ (yyval.statement) = new_throw_statement(ctx, (yyvsp[(2) - (3)].expr)); ;}
break;
case 77:
/* Line 1455 of yacc.c */
-#line 478 "parser.y"
+#line 474 "parser.y"
{ (yyval.statement) = new_try_statement(ctx, (yyvsp[(2) - (3)].statement), (yyvsp[(3) - (3)].catch_block), NULL); ;}
break;
case 78:
/* Line 1455 of yacc.c */
-#line 479 "parser.y"
+#line 475 "parser.y"
{ (yyval.statement) = new_try_statement(ctx, (yyvsp[(2) - (3)].statement), NULL, (yyvsp[(3) - (3)].statement)); ;}
break;
case 79:
/* Line 1455 of yacc.c */
-#line 481 "parser.y"
+#line 477 "parser.y"
{ (yyval.statement) = new_try_statement(ctx, (yyvsp[(2) - (4)].statement), (yyvsp[(3) - (4)].catch_block), (yyvsp[(4) - (4)].statement)); ;}
break;
case 80:
/* Line 1455 of yacc.c */
-#line 486 "parser.y"
+#line 482 "parser.y"
{ (yyval.catch_block) = new_catch_block(ctx, (yyvsp[(3) - (5)].identifier), (yyvsp[(5) - (5)].statement)); ;}
break;
case 81:
/* Line 1455 of yacc.c */
-#line 490 "parser.y"
+#line 486 "parser.y"
{ (yyval.statement) = (yyvsp[(2) - (2)].statement); ;}
break;
case 82:
/* Line 1455 of yacc.c */
-#line 494 "parser.y"
+#line 490 "parser.y"
{ (yyval.expr) = NULL; ;}
break;
case 83:
/* Line 1455 of yacc.c */
-#line 495 "parser.y"
+#line 491 "parser.y"
{ (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
break;
case 84:
/* Line 1455 of yacc.c */
-#line 498 "parser.y"
+#line 494 "parser.y"
{ (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
break;
case 85:
/* Line 1455 of yacc.c */
-#line 499 "parser.y"
- { set_error(ctx, IDS_SYNTAX_ERROR); YYABORT; ;}
+#line 495 "parser.y"
+ { set_error(ctx, JS_E_SYNTAX); YYABORT; ;}
break;
case 86:
/* Line 1455 of yacc.c */
-#line 503 "parser.y"
+#line 499 "parser.y"
{ (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
break;
case 87:
/* Line 1455 of yacc.c */
-#line 505 "parser.y"
+#line 501 "parser.y"
{ (yyval.expr) = new_binary_expression(ctx, EXPR_COMMA, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
break;
case 88:
/* Line 1455 of yacc.c */
-#line 509 "parser.y"
+#line 505 "parser.y"
{ (yyval.expr) = NULL; ;}
break;
case 89:
/* Line 1455 of yacc.c */
-#line 510 "parser.y"
+#line 506 "parser.y"
{ (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
break;
case 90:
/* Line 1455 of yacc.c */
-#line 515 "parser.y"
+#line 511 "parser.y"
{ (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
break;
case 91:
/* Line 1455 of yacc.c */
-#line 517 "parser.y"
+#line 513 "parser.y"
{ (yyval.expr) = new_binary_expression(ctx, EXPR_COMMA, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
break;
case 92:
/* Line 1455 of yacc.c */
-#line 520 "parser.y"
+#line 516 "parser.y"
{ (yyval.ival) = (yyvsp[(1) - (1)].ival); ;}
break;
case 93:
/* Line 1455 of yacc.c */
-#line 521 "parser.y"
+#line 517 "parser.y"
{ (yyval.ival) = EXPR_ASSIGNDIV; ;}
break;
case 94:
/* Line 1455 of yacc.c */
-#line 525 "parser.y"
+#line 521 "parser.y"
{ (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
break;
case 95:
/* Line 1455 of yacc.c */
-#line 527 "parser.y"
+#line 523 "parser.y"
{ (yyval.expr) = new_binary_expression(ctx, EXPR_ASSIGN, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
break;
case 96:
/* Line 1455 of yacc.c */
-#line 529 "parser.y"
+#line 525 "parser.y"
{ (yyval.expr) = new_binary_expression(ctx, (yyvsp[(2) - (3)].ival), (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
break;
case 97:
/* Line 1455 of yacc.c */
-#line 534 "parser.y"
+#line 530 "parser.y"
{ (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
break;
case 98:
/* Line 1455 of yacc.c */
-#line 536 "parser.y"
+#line 532 "parser.y"
{ (yyval.expr) = new_binary_expression(ctx, EXPR_ASSIGN, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
break;
case 99:
/* Line 1455 of yacc.c */
-#line 538 "parser.y"
+#line 534 "parser.y"
{ (yyval.expr) = new_binary_expression(ctx, (yyvsp[(2) - (3)].ival), (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
break;
case 100:
/* Line 1455 of yacc.c */
-#line 542 "parser.y"
+#line 538 "parser.y"
{ (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
break;
case 101:
/* Line 1455 of yacc.c */
-#line 544 "parser.y"
+#line 540 "parser.y"
{ (yyval.expr) = new_conditional_expression(ctx, (yyvsp[(1) - (5)].expr), (yyvsp[(3) - (5)].expr), (yyvsp[(5) - (5)].expr)); ;}
break;
case 102:
/* Line 1455 of yacc.c */
-#line 549 "parser.y"
+#line 545 "parser.y"
{ (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
break;
case 103:
/* Line 1455 of yacc.c */
-#line 551 "parser.y"
+#line 547 "parser.y"
{ (yyval.expr) = new_conditional_expression(ctx, (yyvsp[(1) - (5)].expr), (yyvsp[(3) - (5)].expr), (yyvsp[(5) - (5)].expr)); ;}
break;
case 104:
/* Line 1455 of yacc.c */
-#line 555 "parser.y"
+#line 551 "parser.y"
{ (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
break;
case 105:
/* Line 1455 of yacc.c */
-#line 557 "parser.y"
+#line 553 "parser.y"
{ (yyval.expr) = new_binary_expression(ctx, EXPR_OR, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
break;
case 106:
/* Line 1455 of yacc.c */
-#line 562 "parser.y"
+#line 558 "parser.y"
{ (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
break;
case 107:
/* Line 1455 of yacc.c */
-#line 564 "parser.y"
+#line 560 "parser.y"
{ (yyval.expr) = new_binary_expression(ctx, EXPR_OR, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
break;
case 108:
/* Line 1455 of yacc.c */
-#line 568 "parser.y"
+#line 564 "parser.y"
{ (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
break;
case 109:
/* Line 1455 of yacc.c */
-#line 570 "parser.y"
+#line 566 "parser.y"
{ (yyval.expr) = new_binary_expression(ctx, EXPR_AND, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
break;
case 110:
/* Line 1455 of yacc.c */
-#line 575 "parser.y"
+#line 571 "parser.y"
{ (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
break;
case 111:
/* Line 1455 of yacc.c */
-#line 577 "parser.y"
+#line 573 "parser.y"
{ (yyval.expr) = new_binary_expression(ctx, EXPR_AND, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
break;
case 112:
/* Line 1455 of yacc.c */
-#line 581 "parser.y"
+#line 577 "parser.y"
{ (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
break;
case 113:
/* Line 1455 of yacc.c */
-#line 583 "parser.y"
+#line 579 "parser.y"
{ (yyval.expr) = new_binary_expression(ctx, EXPR_BOR, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
break;
case 114:
/* Line 1455 of yacc.c */
-#line 588 "parser.y"
+#line 584 "parser.y"
{ (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
break;
case 115:
/* Line 1455 of yacc.c */
-#line 590 "parser.y"
+#line 586 "parser.y"
{ (yyval.expr) = new_binary_expression(ctx, EXPR_BOR, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
break;
case 116:
/* Line 1455 of yacc.c */
-#line 594 "parser.y"
+#line 590 "parser.y"
{ (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
break;
case 117:
/* Line 1455 of yacc.c */
-#line 596 "parser.y"
+#line 592 "parser.y"
{ (yyval.expr) = new_binary_expression(ctx, EXPR_BXOR, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
break;
case 118:
/* Line 1455 of yacc.c */
-#line 601 "parser.y"
+#line 597 "parser.y"
{ (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
break;
case 119:
/* Line 1455 of yacc.c */
-#line 603 "parser.y"
+#line 599 "parser.y"
{ (yyval.expr) = new_binary_expression(ctx, EXPR_BXOR, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
break;
case 120:
/* Line 1455 of yacc.c */
-#line 607 "parser.y"
+#line 603 "parser.y"
{ (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
break;
case 121:
/* Line 1455 of yacc.c */
-#line 609 "parser.y"
+#line 605 "parser.y"
{ (yyval.expr) = new_binary_expression(ctx, EXPR_BAND, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
break;
case 122:
/* Line 1455 of yacc.c */
-#line 614 "parser.y"
+#line 610 "parser.y"
{ (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
break;
case 123:
/* Line 1455 of yacc.c */
-#line 616 "parser.y"
+#line 612 "parser.y"
{ (yyval.expr) = new_binary_expression(ctx, EXPR_BAND, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
break;
case 124:
/* Line 1455 of yacc.c */
-#line 620 "parser.y"
+#line 616 "parser.y"
{ (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
break;
case 125:
/* Line 1455 of yacc.c */
-#line 622 "parser.y"
+#line 618 "parser.y"
{ (yyval.expr) = new_binary_expression(ctx, (yyvsp[(2) - (3)].ival), (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
break;
case 126:
/* Line 1455 of yacc.c */
-#line 626 "parser.y"
+#line 622 "parser.y"
{ (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
break;
case 127:
/* Line 1455 of yacc.c */
-#line 628 "parser.y"
+#line 624 "parser.y"
{ (yyval.expr) = new_binary_expression(ctx, (yyvsp[(2) - (3)].ival), (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
break;
case 128:
/* Line 1455 of yacc.c */
-#line 632 "parser.y"
+#line 628 "parser.y"
{ (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
break;
case 129:
/* Line 1455 of yacc.c */
-#line 634 "parser.y"
+#line 630 "parser.y"
{ (yyval.expr) = new_binary_expression(ctx, (yyvsp[(2) - (3)].ival), (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
break;
case 130:
/* Line 1455 of yacc.c */
-#line 636 "parser.y"
+#line 632 "parser.y"
{ (yyval.expr) = new_binary_expression(ctx, EXPR_INSTANCEOF, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
break;
case 131:
/* Line 1455 of yacc.c */
-#line 638 "parser.y"
+#line 634 "parser.y"
{ (yyval.expr) = new_binary_expression(ctx, EXPR_IN, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
break;
case 132:
/* Line 1455 of yacc.c */
-#line 642 "parser.y"
+#line 638 "parser.y"
{ (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
break;
case 133:
/* Line 1455 of yacc.c */
-#line 644 "parser.y"
+#line 640 "parser.y"
{ (yyval.expr) = new_binary_expression(ctx, (yyvsp[(2) - (3)].ival), (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
break;
case 134:
/* Line 1455 of yacc.c */
-#line 646 "parser.y"
+#line 642 "parser.y"
{ (yyval.expr) = new_binary_expression(ctx, EXPR_INSTANCEOF, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
break;
case 135:
/* Line 1455 of yacc.c */
-#line 650 "parser.y"
+#line 646 "parser.y"
{ (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
break;
case 136:
/* Line 1455 of yacc.c */
-#line 652 "parser.y"
+#line 648 "parser.y"
{ (yyval.expr) = new_binary_expression(ctx, (yyvsp[(2) - (3)].ival), (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
break;
case 137:
/* Line 1455 of yacc.c */
-#line 657 "parser.y"
+#line 653 "parser.y"
{ (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
break;
case 138:
/* Line 1455 of yacc.c */
-#line 659 "parser.y"
+#line 655 "parser.y"
{ (yyval.expr) = new_binary_expression(ctx, EXPR_ADD, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
break;
case 139:
/* Line 1455 of yacc.c */
-#line 661 "parser.y"
+#line 657 "parser.y"
{ (yyval.expr) = new_binary_expression(ctx, EXPR_SUB, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
break;
case 140:
/* Line 1455 of yacc.c */
-#line 665 "parser.y"
+#line 661 "parser.y"
{ (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
break;
case 141:
/* Line 1455 of yacc.c */
-#line 667 "parser.y"
+#line 663 "parser.y"
{ (yyval.expr) = new_binary_expression(ctx, EXPR_MUL, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
break;
case 142:
/* Line 1455 of yacc.c */
-#line 669 "parser.y"
+#line 665 "parser.y"
{ (yyval.expr) = new_binary_expression(ctx, EXPR_DIV, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
break;
case 143:
/* Line 1455 of yacc.c */
-#line 671 "parser.y"
+#line 667 "parser.y"
{ (yyval.expr) = new_binary_expression(ctx, EXPR_MOD, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
break;
case 144:
/* Line 1455 of yacc.c */
-#line 675 "parser.y"
+#line 671 "parser.y"
{ (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
break;
case 145:
/* Line 1455 of yacc.c */
-#line 677 "parser.y"
+#line 673 "parser.y"
{ (yyval.expr) = new_unary_expression(ctx, EXPR_DELETE, (yyvsp[(2) - (2)].expr)); ;}
break;
case 146:
/* Line 1455 of yacc.c */
-#line 678 "parser.y"
+#line 674 "parser.y"
{ (yyval.expr) = new_unary_expression(ctx, EXPR_VOID, (yyvsp[(2) - (2)].expr)); ;}
break;
case 147:
/* Line 1455 of yacc.c */
-#line 680 "parser.y"
+#line 676 "parser.y"
{ (yyval.expr) = new_unary_expression(ctx, EXPR_TYPEOF, (yyvsp[(2) - (2)].expr)); ;}
break;
case 148:
/* Line 1455 of yacc.c */
-#line 681 "parser.y"
+#line 677 "parser.y"
{ (yyval.expr) = new_unary_expression(ctx, EXPR_PREINC, (yyvsp[(2) - (2)].expr)); ;}
break;
case 149:
/* Line 1455 of yacc.c */
-#line 682 "parser.y"
+#line 678 "parser.y"
{ (yyval.expr) = new_unary_expression(ctx, EXPR_PREDEC, (yyvsp[(2) - (2)].expr)); ;}
break;
case 150:
/* Line 1455 of yacc.c */
-#line 683 "parser.y"
+#line 679 "parser.y"
{ (yyval.expr) = new_unary_expression(ctx, EXPR_PLUS, (yyvsp[(2) - (2)].expr)); ;}
break;
case 151:
/* Line 1455 of yacc.c */
-#line 684 "parser.y"
+#line 680 "parser.y"
{ (yyval.expr) = new_unary_expression(ctx, EXPR_MINUS, (yyvsp[(2) - (2)].expr)); ;}
break;
case 152:
/* Line 1455 of yacc.c */
-#line 685 "parser.y"
+#line 681 "parser.y"
{ (yyval.expr) = new_unary_expression(ctx, EXPR_BITNEG, (yyvsp[(2) - (2)].expr)); ;}
break;
case 153:
/* Line 1455 of yacc.c */
-#line 686 "parser.y"
+#line 682 "parser.y"
{ (yyval.expr) = new_unary_expression(ctx, EXPR_LOGNEG, (yyvsp[(2) - (2)].expr)); ;}
break;
case 154:
/* Line 1455 of yacc.c */
-#line 691 "parser.y"
+#line 687 "parser.y"
{ (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
break;
case 155:
/* Line 1455 of yacc.c */
-#line 693 "parser.y"
+#line 689 "parser.y"
{ (yyval.expr) = new_unary_expression(ctx, EXPR_POSTINC, (yyvsp[(1) - (2)].expr)); ;}
break;
case 156:
/* Line 1455 of yacc.c */
-#line 695 "parser.y"
+#line 691 "parser.y"
{ (yyval.expr) = new_unary_expression(ctx, EXPR_POSTDEC, (yyvsp[(1) - (2)].expr)); ;}
break;
case 157:
/* Line 1455 of yacc.c */
-#line 700 "parser.y"
+#line 696 "parser.y"
{ (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
break;
case 158:
/* Line 1455 of yacc.c */
-#line 701 "parser.y"
+#line 697 "parser.y"
{ (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
break;
case 159:
/* Line 1455 of yacc.c */
-#line 705 "parser.y"
+#line 701 "parser.y"
{ (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
break;
case 160:
/* Line 1455 of yacc.c */
-#line 706 "parser.y"
+#line 702 "parser.y"
{ (yyval.expr) = new_new_expression(ctx, (yyvsp[(2) - (2)].expr), NULL); ;}
break;
case 161:
/* Line 1455 of yacc.c */
-#line 710 "parser.y"
+#line 706 "parser.y"
{ (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
break;
case 162:
/* Line 1455 of yacc.c */
-#line 711 "parser.y"
+#line 707 "parser.y"
{ (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
break;
case 163:
/* Line 1455 of yacc.c */
-#line 713 "parser.y"
- { (yyval.expr) = new_array_expression(ctx, (yyvsp[(1) - (4)].expr), (yyvsp[(3) - (4)].expr)); ;}
+#line 709 "parser.y"
+ { (yyval.expr) = new_binary_expression(ctx, EXPR_ARRAY, (yyvsp[(1) - (4)].expr), (yyvsp[(3) - (4)].expr)); ;}
break;
case 164:
/* Line 1455 of yacc.c */
-#line 715 "parser.y"
+#line 711 "parser.y"
{ (yyval.expr) = new_member_expression(ctx, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].identifier)); ;}
break;
case 165:
/* Line 1455 of yacc.c */
-#line 717 "parser.y"
+#line 713 "parser.y"
{ (yyval.expr) = new_new_expression(ctx, (yyvsp[(2) - (3)].expr), (yyvsp[(3) - (3)].argument_list)); ;}
break;
case 166:
/* Line 1455 of yacc.c */
-#line 722 "parser.y"
+#line 718 "parser.y"
{ (yyval.expr) = new_call_expression(ctx, (yyvsp[(1) - (2)].expr), (yyvsp[(2) - (2)].argument_list)); ;}
break;
case 167:
/* Line 1455 of yacc.c */
-#line 724 "parser.y"
+#line 720 "parser.y"
{ (yyval.expr) = new_call_expression(ctx, (yyvsp[(1) - (2)].expr), (yyvsp[(2) - (2)].argument_list)); ;}
break;
case 168:
/* Line 1455 of yacc.c */
-#line 726 "parser.y"
- { (yyval.expr) = new_array_expression(ctx, (yyvsp[(1) - (4)].expr), (yyvsp[(3) - (4)].expr)); ;}
+#line 722 "parser.y"
+ { (yyval.expr) = new_binary_expression(ctx, EXPR_ARRAY, (yyvsp[(1) - (4)].expr), (yyvsp[(3) - (4)].expr)); ;}
break;
case 169:
/* Line 1455 of yacc.c */
-#line 728 "parser.y"
+#line 724 "parser.y"
{ (yyval.expr) = new_member_expression(ctx, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].identifier)); ;}
break;
case 170:
/* Line 1455 of yacc.c */
-#line 732 "parser.y"
+#line 728 "parser.y"
{ (yyval.argument_list) = NULL; ;}
break;
case 171:
/* Line 1455 of yacc.c */
-#line 733 "parser.y"
+#line 729 "parser.y"
{ (yyval.argument_list) = (yyvsp[(2) - (3)].argument_list); ;}
break;
case 172:
/* Line 1455 of yacc.c */
-#line 737 "parser.y"
+#line 733 "parser.y"
{ (yyval.argument_list) = new_argument_list(ctx, (yyvsp[(1) - (1)].expr)); ;}
break;
case 173:
/* Line 1455 of yacc.c */
-#line 739 "parser.y"
+#line 735 "parser.y"
{ (yyval.argument_list) = argument_list_add(ctx, (yyvsp[(1) - (3)].argument_list), (yyvsp[(3) - (3)].expr)); ;}
break;
case 174:
/* Line 1455 of yacc.c */
-#line 743 "parser.y"
- { (yyval.expr) = new_this_expression(ctx); ;}
+#line 739 "parser.y"
+ { (yyval.expr) = new_expression(ctx, EXPR_THIS, 0); ;}
break;
case 175:
/* Line 1455 of yacc.c */
-#line 744 "parser.y"
+#line 740 "parser.y"
{ (yyval.expr) = new_identifier_expression(ctx, (yyvsp[(1) - (1)].identifier)); ;}
break;
case 176:
/* Line 1455 of yacc.c */
-#line 745 "parser.y"
+#line 741 "parser.y"
{ (yyval.expr) = new_literal_expression(ctx, (yyvsp[(1) - (1)].literal)); ;}
break;
case 177:
/* Line 1455 of yacc.c */
-#line 746 "parser.y"
+#line 742 "parser.y"
{ (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
break;
case 178:
/* Line 1455 of yacc.c */
-#line 747 "parser.y"
+#line 743 "parser.y"
{ (yyval.expr) = (yyvsp[(1) - (1)].expr); ;}
break;
case 179:
/* Line 1455 of yacc.c */
-#line 748 "parser.y"
+#line 744 "parser.y"
{ (yyval.expr) = (yyvsp[(2) - (3)].expr); ;}
break;
case 180:
/* Line 1455 of yacc.c */
-#line 752 "parser.y"
+#line 748 "parser.y"
{ (yyval.expr) = new_array_literal_expression(ctx, NULL, 0); ;}
break;
case 181:
/* Line 1455 of yacc.c */
-#line 753 "parser.y"
+#line 749 "parser.y"
{ (yyval.expr) = new_array_literal_expression(ctx, NULL, (yyvsp[(2) - (3)].ival)+1); ;}
break;
case 182:
/* Line 1455 of yacc.c */
-#line 754 "parser.y"
+#line 750 "parser.y"
{ (yyval.expr) = new_array_literal_expression(ctx, (yyvsp[(2) - (3)].element_list), 0); ;}
break;
case 183:
/* Line 1455 of yacc.c */
-#line 756 "parser.y"
+#line 752 "parser.y"
{ (yyval.expr) = new_array_literal_expression(ctx, (yyvsp[(2) - (5)].element_list), (yyvsp[(4) - (5)].ival)+1); ;}
break;
case 184:
/* Line 1455 of yacc.c */
-#line 761 "parser.y"
+#line 757 "parser.y"
{ (yyval.element_list) = new_element_list(ctx, (yyvsp[(1) - (2)].ival), (yyvsp[(2) - (2)].expr)); ;}
break;
case 185:
/* Line 1455 of yacc.c */
-#line 763 "parser.y"
+#line 759 "parser.y"
{ (yyval.element_list) = element_list_add(ctx, (yyvsp[(1) - (4)].element_list), (yyvsp[(3) - (4)].ival), (yyvsp[(4) - (4)].expr)); ;}
break;
case 186:
/* Line 1455 of yacc.c */
-#line 767 "parser.y"
+#line 763 "parser.y"
{ (yyval.ival) = 1; ;}
break;
case 187:
/* Line 1455 of yacc.c */
-#line 768 "parser.y"
+#line 764 "parser.y"
{ (yyval.ival) = (yyvsp[(1) - (2)].ival) + 1; ;}
break;
case 188:
/* Line 1455 of yacc.c */
-#line 772 "parser.y"
+#line 768 "parser.y"
{ (yyval.ival) = 0; ;}
break;
case 189:
/* Line 1455 of yacc.c */
-#line 773 "parser.y"
+#line 769 "parser.y"
{ (yyval.ival) = (yyvsp[(1) - (1)].ival); ;}
break;
case 190:
/* Line 1455 of yacc.c */
-#line 777 "parser.y"
+#line 773 "parser.y"
{ (yyval.expr) = new_prop_and_value_expression(ctx, NULL); ;}
break;
case 191:
/* Line 1455 of yacc.c */
-#line 779 "parser.y"
+#line 775 "parser.y"
{ (yyval.expr) = new_prop_and_value_expression(ctx, (yyvsp[(2) - (3)].property_list)); ;}
break;
case 192:
/* Line 1455 of yacc.c */
-#line 784 "parser.y"
+#line 780 "parser.y"
{ (yyval.property_list) = new_property_list(ctx, (yyvsp[(1) - (3)].literal), (yyvsp[(3) - (3)].expr)); ;}
break;
case 193:
/* Line 1455 of yacc.c */
-#line 786 "parser.y"
+#line 782 "parser.y"
{ (yyval.property_list) = property_list_add(ctx, (yyvsp[(1) - (5)].property_list), (yyvsp[(3) - (5)].literal), (yyvsp[(5) - (5)].expr)); ;}
break;
case 194:
/* Line 1455 of yacc.c */
-#line 790 "parser.y"
+#line 786 "parser.y"
{ (yyval.literal) = new_string_literal(ctx, (yyvsp[(1) - (1)].identifier)); ;}
break;
case 195:
/* Line 1455 of yacc.c */
-#line 791 "parser.y"
+#line 787 "parser.y"
{ (yyval.literal) = new_string_literal(ctx, (yyvsp[(1) - (1)].wstr)); ;}
break;
case 196:
/* Line 1455 of yacc.c */
-#line 792 "parser.y"
+#line 788 "parser.y"
{ (yyval.literal) = (yyvsp[(1) - (1)].literal); ;}
break;
case 197:
/* Line 1455 of yacc.c */
-#line 796 "parser.y"
+#line 792 "parser.y"
{ (yyval.identifier) = NULL; ;}
break;
case 198:
/* Line 1455 of yacc.c */
-#line 797 "parser.y"
+#line 793 "parser.y"
{ (yyval.identifier) = (yyvsp[(1) - (1)].identifier); ;}
break;
case 199:
/* Line 1455 of yacc.c */
-#line 801 "parser.y"
+#line 797 "parser.y"
{ (yyval.literal) = new_null_literal(ctx); ;}
break;
case 200:
/* Line 1455 of yacc.c */
-#line 802 "parser.y"
+#line 798 "parser.y"
{ (yyval.literal) = (yyvsp[(1) - (1)].literal); ;}
break;
case 201:
/* Line 1455 of yacc.c */
-#line 803 "parser.y"
+#line 799 "parser.y"
{ (yyval.literal) = (yyvsp[(1) - (1)].literal); ;}
break;
case 202:
/* Line 1455 of yacc.c */
-#line 804 "parser.y"
+#line 800 "parser.y"
{ (yyval.literal) = new_string_literal(ctx, (yyvsp[(1) - (1)].wstr)); ;}
break;
case 203:
/* Line 1455 of yacc.c */
-#line 805 "parser.y"
+#line 801 "parser.y"
{ (yyval.literal) = parse_regexp(ctx);
if(!(yyval.literal)) YYABORT; ;}
break;
case 204:
/* Line 1455 of yacc.c */
-#line 807 "parser.y"
+#line 803 "parser.y"
{ (yyval.literal) = parse_regexp(ctx);
if(!(yyval.literal)) YYABORT; ;}
break;
case 205:
/* Line 1455 of yacc.c */
-#line 812 "parser.y"
+#line 808 "parser.y"
{ (yyval.literal) = new_boolean_literal(ctx, VARIANT_TRUE); ;}
break;
case 206:
/* Line 1455 of yacc.c */
-#line 813 "parser.y"
+#line 809 "parser.y"
{ (yyval.literal) = new_boolean_literal(ctx, VARIANT_FALSE); ;}
break;
- case 208:
+ case 207:
+
+/* Line 1455 of yacc.c */
+#line 810 "parser.y"
+ { (yyval.literal) = (yyvsp[(1) - (1)].literal); ;}
+ break;
+
+ case 209:
/* Line 1455 of yacc.c */
-#line 817 "parser.y"
+#line 814 "parser.y"
{ if(!allow_auto_semicolon(ctx)) {YYABORT;} ;}
break;
- case 210:
+ case 211:
/* Line 1455 of yacc.c */
-#line 821 "parser.y"
- { set_error(ctx, IDS_LBRACKET); YYABORT; ;}
+#line 818 "parser.y"
+ { set_error(ctx, JS_E_MISSING_LBRACKET); YYABORT; ;}
break;
- case 212:
+ case 213:
/* Line 1455 of yacc.c */
-#line 825 "parser.y"
- { set_error(ctx, IDS_RBRACKET); YYABORT; ;}
+#line 822 "parser.y"
+ { set_error(ctx, JS_E_MISSING_RBRACKET); YYABORT; ;}
break;
- case 214:
+ case 215:
/* Line 1455 of yacc.c */
-#line 829 "parser.y"
- { set_error(ctx, IDS_SEMICOLON); YYABORT; ;}
+#line 826 "parser.y"
+ { set_error(ctx, JS_E_MISSING_SEMICOLON); YYABORT; ;}
break;
/* Line 1455 of yacc.c */
-#line 3497 "parser.tab.c"
+#line 3507 "parser.tab.c"
default: break;
}
YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
/* Line 1675 of yacc.c */
-#line 831 "parser.y"
+#line 828 "parser.y"
static BOOL allow_auto_semicolon(parser_ctx_t *ctx)
return ctx->nl || ctx->ptr == ctx->end || *(ctx->ptr-1) == '}';
}
-static literal_t *new_string_literal(parser_ctx_t *ctx, const WCHAR *str)
+static void *new_statement(parser_ctx_t *ctx, statement_type_t type, size_t size)
{
- literal_t *ret = parser_alloc(ctx, sizeof(literal_t));
+ statement_t *stat;
- ret->type = LT_STRING;
- ret->u.wstr = str;
+ stat = parser_alloc(ctx, size ? size : sizeof(*stat));
+ if(!stat)
+ return NULL;
- return ret;
+ stat->type = type;
+ stat->next = NULL;
+
+ return stat;
}
-static literal_t *new_null_literal(parser_ctx_t *ctx)
+static literal_t *new_string_literal(parser_ctx_t *ctx, const WCHAR *str)
{
literal_t *ret = parser_alloc(ctx, sizeof(literal_t));
- ret->type = LT_NULL;
+ ret->type = LT_STRING;
+ ret->u.wstr = str;
return ret;
}
-static literal_t *new_boolean_literal(parser_ctx_t *ctx, VARIANT_BOOL bval)
+static literal_t *new_null_literal(parser_ctx_t *ctx)
{
literal_t *ret = parser_alloc(ctx, sizeof(literal_t));
- ret->type = LT_BOOL;
- ret->u.bval = bval;
+ ret->type = LT_NULL;
return ret;
}
static statement_t *new_block_statement(parser_ctx_t *ctx, statement_list_t *list)
{
- block_statement_t *ret = parser_alloc(ctx, sizeof(block_statement_t));
+ block_statement_t *ret;
+
+ ret = new_statement(ctx, STAT_BLOCK, sizeof(*ret));
+ if(!ret)
+ return NULL;
- ret->stat.eval = block_statement_eval;
- ret->stat.next = NULL;
ret->stat_list = list ? list->head : NULL;
return &ret->stat;
static variable_declaration_t *new_variable_declaration(parser_ctx_t *ctx, const WCHAR *identifier, expression_t *expr)
{
variable_declaration_t *ret = parser_alloc(ctx, sizeof(variable_declaration_t));
- var_list_t *var_list = parser_alloc(ctx, sizeof(var_list_t));
ret->identifier = identifier;
ret->expr = expr;
ret->next = NULL;
-
- var_list->identifier = identifier;
- var_list->next = NULL;
-
- if(ctx->func_stack->var_tail)
- ctx->func_stack->var_tail = ctx->func_stack->var_tail->next = var_list;
- else
- ctx->func_stack->var_head = ctx->func_stack->var_tail = var_list;
+ ret->global_next = NULL;
return ret;
}
static statement_t *new_var_statement(parser_ctx_t *ctx, variable_list_t *variable_list)
{
- var_statement_t *ret = parser_alloc(ctx, sizeof(var_statement_t));
+ var_statement_t *ret;
+
+ ret = new_statement(ctx, STAT_VAR, sizeof(*ret));
+ if(!ret)
+ return NULL;
- ret->stat.eval = var_statement_eval;
- ret->stat.next = NULL;
ret->variable_list = variable_list->head;
return &ret->stat;
}
-static statement_t *new_empty_statement(parser_ctx_t *ctx)
-{
- statement_t *ret = parser_alloc(ctx, sizeof(statement_t));
-
- ret->eval = empty_statement_eval;
- ret->next = NULL;
-
- return ret;
-}
-
static statement_t *new_expression_statement(parser_ctx_t *ctx, expression_t *expr)
{
- expression_statement_t *ret = parser_alloc(ctx, sizeof(expression_statement_t));
+ expression_statement_t *ret;
+
+ ret = new_statement(ctx, STAT_EXPR, sizeof(*ret));
+ if(!ret)
+ return NULL;
- ret->stat.eval = expression_statement_eval;
- ret->stat.next = NULL;
ret->expr = expr;
return &ret->stat;
static statement_t *new_if_statement(parser_ctx_t *ctx, expression_t *expr, statement_t *if_stat, statement_t *else_stat)
{
- if_statement_t *ret = parser_alloc(ctx, sizeof(if_statement_t));
+ if_statement_t *ret;
+
+ ret = new_statement(ctx, STAT_IF, sizeof(*ret));
+ if(!ret)
+ return NULL;
- ret->stat.eval = if_statement_eval;
- ret->stat.next = NULL;
ret->expr = expr;
ret->if_stat = if_stat;
ret->else_stat = else_stat;
static statement_t *new_while_statement(parser_ctx_t *ctx, BOOL dowhile, expression_t *expr, statement_t *stat)
{
- while_statement_t *ret = parser_alloc(ctx, sizeof(while_statement_t));
+ while_statement_t *ret;
+
+ ret = new_statement(ctx, STAT_WHILE, sizeof(*ret));
+ if(!ret)
+ return NULL;
- ret->stat.eval = while_statement_eval;
- ret->stat.next = NULL;
ret->do_while = dowhile;
ret->expr = expr;
ret->statement = stat;
static statement_t *new_for_statement(parser_ctx_t *ctx, variable_list_t *variable_list, expression_t *begin_expr,
expression_t *expr, expression_t *end_expr, statement_t *statement)
{
- for_statement_t *ret = parser_alloc(ctx, sizeof(for_statement_t));
+ for_statement_t *ret;
+
+ ret = new_statement(ctx, STAT_FOR, sizeof(*ret));
+ if(!ret)
+ return NULL;
- ret->stat.eval = for_statement_eval;
- ret->stat.next = NULL;
ret->variable_list = variable_list ? variable_list->head : NULL;
ret->begin_expr = begin_expr;
ret->expr = expr;
static statement_t *new_forin_statement(parser_ctx_t *ctx, variable_declaration_t *variable, expression_t *expr,
expression_t *in_expr, statement_t *statement)
{
- forin_statement_t *ret = parser_alloc(ctx, sizeof(forin_statement_t));
+ forin_statement_t *ret;
+
+ ret = new_statement(ctx, STAT_FORIN, sizeof(*ret));
+ if(!ret)
+ return NULL;
- ret->stat.eval = forin_statement_eval;
- ret->stat.next = NULL;
ret->variable = variable;
ret->expr = expr;
ret->in_expr = in_expr;
static statement_t *new_continue_statement(parser_ctx_t *ctx, const WCHAR *identifier)
{
- branch_statement_t *ret = parser_alloc(ctx, sizeof(branch_statement_t));
+ branch_statement_t *ret;
+
+ ret = new_statement(ctx, STAT_CONTINUE, sizeof(*ret));
+ if(!ret)
+ return NULL;
- ret->stat.eval = continue_statement_eval;
- ret->stat.next = NULL;
ret->identifier = identifier;
return &ret->stat;
static statement_t *new_break_statement(parser_ctx_t *ctx, const WCHAR *identifier)
{
- branch_statement_t *ret = parser_alloc(ctx, sizeof(branch_statement_t));
+ branch_statement_t *ret;
+
+ ret = new_statement(ctx, STAT_BREAK, sizeof(*ret));
+ if(!ret)
+ return NULL;
- ret->stat.eval = break_statement_eval;
- ret->stat.next = NULL;
ret->identifier = identifier;
return &ret->stat;
static statement_t *new_return_statement(parser_ctx_t *ctx, expression_t *expr)
{
- expression_statement_t *ret = parser_alloc(ctx, sizeof(expression_statement_t));
+ expression_statement_t *ret;
+
+ ret = new_statement(ctx, STAT_RETURN, sizeof(*ret));
+ if(!ret)
+ return NULL;
- ret->stat.eval = return_statement_eval;
- ret->stat.next = NULL;
ret->expr = expr;
return &ret->stat;
static statement_t *new_with_statement(parser_ctx_t *ctx, expression_t *expr, statement_t *statement)
{
- with_statement_t *ret = parser_alloc(ctx, sizeof(with_statement_t));
+ with_statement_t *ret;
+
+ ret = new_statement(ctx, STAT_WITH, sizeof(*ret));
+ if(!ret)
+ return NULL;
- ret->stat.eval = with_statement_eval;
- ret->stat.next = NULL;
ret->expr = expr;
ret->statement = statement;
static statement_t *new_labelled_statement(parser_ctx_t *ctx, const WCHAR *identifier, statement_t *statement)
{
- labelled_statement_t *ret = parser_alloc(ctx, sizeof(labelled_statement_t));
+ labelled_statement_t *ret;
+
+ ret = new_statement(ctx, STAT_LABEL, sizeof(*ret));
+ if(!ret)
+ return NULL;
- ret->stat.eval = labelled_statement_eval;
- ret->stat.next = NULL;
ret->identifier = identifier;
ret->statement = statement;
static statement_t *new_switch_statement(parser_ctx_t *ctx, expression_t *expr, case_clausule_t *case_list)
{
- switch_statement_t *ret = parser_alloc(ctx, sizeof(switch_statement_t));
+ switch_statement_t *ret;
+
+ ret = new_statement(ctx, STAT_SWITCH, sizeof(*ret));
+ if(!ret)
+ return NULL;
- ret->stat.eval = switch_statement_eval;
- ret->stat.next = NULL;
ret->expr = expr;
ret->case_list = case_list;
static statement_t *new_throw_statement(parser_ctx_t *ctx, expression_t *expr)
{
- expression_statement_t *ret = parser_alloc(ctx, sizeof(expression_statement_t));
+ expression_statement_t *ret;
+
+ ret = new_statement(ctx, STAT_THROW, sizeof(*ret));
+ if(!ret)
+ return NULL;
- ret->stat.eval = throw_statement_eval;
- ret->stat.next = NULL;
ret->expr = expr;
return &ret->stat;
static statement_t *new_try_statement(parser_ctx_t *ctx, statement_t *try_statement,
catch_block_t *catch_block, statement_t *finally_statement)
{
- try_statement_t *ret = parser_alloc(ctx, sizeof(try_statement_t));
+ try_statement_t *ret;
+
+ ret = new_statement(ctx, STAT_TRY, sizeof(*ret));
+ if(!ret)
+ return NULL;
- ret->stat.eval = try_statement_eval;
- ret->stat.next = NULL;
ret->try_statement = try_statement;
ret->catch_block = catch_block;
ret->finally_statement = finally_statement;
static expression_t *new_function_expression(parser_ctx_t *ctx, const WCHAR *identifier,
parameter_list_t *parameter_list, source_elements_t *source_elements, const WCHAR *src_str, DWORD src_len)
{
- function_expression_t *ret = parser_alloc(ctx, sizeof(function_expression_t));
+ function_expression_t *ret = new_expression(ctx, EXPR_FUNC, sizeof(*ret));
- ret->expr.eval = function_expression_eval;
ret->identifier = identifier;
ret->parameter_list = parameter_list ? parameter_list->head : NULL;
ret->source_elements = source_elements;
ret->src_str = src_str;
ret->src_len = src_len;
+ ret->next = NULL;
- if(ret->identifier) {
- function_declaration_t *decl = parser_alloc(ctx, sizeof(function_declaration_t));
+ return &ret->expr;
+}
- decl->expr = ret;
- decl->next = NULL;
+static void *new_expression(parser_ctx_t *ctx, expression_type_t type, size_t size)
+{
+ expression_t *ret = parser_alloc(ctx, size ? size : sizeof(*ret));
- if(ctx->func_stack->func_tail)
- ctx->func_stack->func_tail = ctx->func_stack->func_tail->next = decl;
- else
- ctx->func_stack->func_head = ctx->func_stack->func_tail = decl;
- }
+ ret->type = type;
- return &ret->expr;
+ return ret;
}
-static const expression_eval_t expression_eval_table[] = {
- comma_expression_eval,
- logical_or_expression_eval,
- logical_and_expression_eval,
- binary_or_expression_eval,
- binary_xor_expression_eval,
- binary_and_expression_eval,
- instanceof_expression_eval,
- in_expression_eval,
- add_expression_eval,
- sub_expression_eval,
- mul_expression_eval,
- div_expression_eval,
- mod_expression_eval,
- delete_expression_eval,
- void_expression_eval,
- typeof_expression_eval,
- minus_expression_eval,
- plus_expression_eval,
- post_increment_expression_eval,
- post_decrement_expression_eval,
- pre_increment_expression_eval,
- pre_decrement_expression_eval,
- equal_expression_eval,
- equal2_expression_eval,
- not_equal_expression_eval,
- not_equal2_expression_eval,
- less_expression_eval,
- lesseq_expression_eval,
- greater_expression_eval,
- greatereq_expression_eval,
- binary_negation_expression_eval,
- logical_negation_expression_eval,
- left_shift_expression_eval,
- right_shift_expression_eval,
- right2_shift_expression_eval,
- assign_expression_eval,
- assign_lshift_expression_eval,
- assign_rshift_expression_eval,
- assign_rrshift_expression_eval,
- assign_add_expression_eval,
- assign_sub_expression_eval,
- assign_mul_expression_eval,
- assign_div_expression_eval,
- assign_mod_expression_eval,
- assign_and_expression_eval,
- assign_or_expression_eval,
- assign_xor_expression_eval,
-};
-
static expression_t *new_binary_expression(parser_ctx_t *ctx, expression_type_t type,
expression_t *expression1, expression_t *expression2)
{
- binary_expression_t *ret = parser_alloc(ctx, sizeof(binary_expression_t));
+ binary_expression_t *ret = new_expression(ctx, type, sizeof(*ret));
- ret->expr.eval = expression_eval_table[type];
ret->expression1 = expression1;
ret->expression2 = expression2;
static expression_t *new_unary_expression(parser_ctx_t *ctx, expression_type_t type, expression_t *expression)
{
- unary_expression_t *ret = parser_alloc(ctx, sizeof(unary_expression_t));
+ unary_expression_t *ret = new_expression(ctx, type, sizeof(*ret));
- ret->expr.eval = expression_eval_table[type];
ret->expression = expression;
return &ret->expr;
static expression_t *new_conditional_expression(parser_ctx_t *ctx, expression_t *expression,
expression_t *true_expression, expression_t *false_expression)
{
- conditional_expression_t *ret = parser_alloc(ctx, sizeof(conditional_expression_t));
+ conditional_expression_t *ret = new_expression(ctx, EXPR_COND, sizeof(*ret));
- ret->expr.eval = conditional_expression_eval;
ret->expression = expression;
ret->true_expression = true_expression;
ret->false_expression = false_expression;
return &ret->expr;
}
-static expression_t *new_array_expression(parser_ctx_t *ctx, expression_t *member_expr, expression_t *expression)
-{
- array_expression_t *ret = parser_alloc(ctx, sizeof(array_expression_t));
-
- ret->expr.eval = array_expression_eval;
- ret->member_expr = member_expr;
- ret->expression = expression;
-
- return &ret->expr;
-}
-
static expression_t *new_member_expression(parser_ctx_t *ctx, expression_t *expression, const WCHAR *identifier)
{
- member_expression_t *ret = parser_alloc(ctx, sizeof(member_expression_t));
+ member_expression_t *ret = new_expression(ctx, EXPR_MEMBER, sizeof(*ret));
- ret->expr.eval = member_expression_eval;
ret->expression = expression;
ret->identifier = identifier;
static expression_t *new_new_expression(parser_ctx_t *ctx, expression_t *expression, argument_list_t *argument_list)
{
- call_expression_t *ret = parser_alloc(ctx, sizeof(call_expression_t));
+ call_expression_t *ret = new_expression(ctx, EXPR_NEW, sizeof(*ret));
- ret->expr.eval = new_expression_eval;
ret->expression = expression;
ret->argument_list = argument_list ? argument_list->head : NULL;
static expression_t *new_call_expression(parser_ctx_t *ctx, expression_t *expression, argument_list_t *argument_list)
{
- call_expression_t *ret = parser_alloc(ctx, sizeof(call_expression_t));
+ call_expression_t *ret = new_expression(ctx, EXPR_CALL, sizeof(*ret));
- ret->expr.eval = call_expression_eval;
ret->expression = expression;
ret->argument_list = argument_list ? argument_list->head : NULL;
return &ret->expr;
}
-static expression_t *new_this_expression(parser_ctx_t *ctx)
-{
- expression_t *ret = parser_alloc(ctx, sizeof(expression_t));
-
- ret->eval = this_expression_eval;
-
- return ret;
-}
-
static int parser_error(const char *str)
{
return 0;
static void set_error(parser_ctx_t *ctx, UINT error)
{
- ctx->hres = JSCRIPT_ERROR|error;
+ ctx->hres = error;
}
static BOOL explicit_error(parser_ctx_t *ctx, void *obj, WCHAR next)
{
if(obj || *(ctx->ptr-1)==next) return TRUE;
- set_error(ctx, IDS_SYNTAX_ERROR);
+ set_error(ctx, JS_E_SYNTAX);
return FALSE;
}
static expression_t *new_identifier_expression(parser_ctx_t *ctx, const WCHAR *identifier)
{
- identifier_expression_t *ret = parser_alloc(ctx, sizeof(identifier_expression_t));
+ identifier_expression_t *ret = new_expression(ctx, EXPR_IDENT, sizeof(*ret));
- ret->expr.eval = identifier_expression_eval;
ret->identifier = identifier;
return &ret->expr;
static expression_t *new_array_literal_expression(parser_ctx_t *ctx, element_list_t *element_list, int length)
{
- array_literal_expression_t *ret = parser_alloc(ctx, sizeof(array_literal_expression_t));
+ array_literal_expression_t *ret = new_expression(ctx, EXPR_ARRAYLIT, sizeof(*ret));
- ret->expr.eval = array_literal_expression_eval;
ret->element_list = element_list ? element_list->head : NULL;
ret->length = length;
static expression_t *new_prop_and_value_expression(parser_ctx_t *ctx, property_list_t *property_list)
{
- property_value_expression_t *ret = parser_alloc(ctx, sizeof(property_value_expression_t));
+ property_value_expression_t *ret = new_expression(ctx, EXPR_PROPVAL, sizeof(*ret));
- ret->expr.eval = property_value_expression_eval;
ret->property_list = property_list ? property_list->head : NULL;
return &ret->expr;
static expression_t *new_literal_expression(parser_ctx_t *ctx, literal_t *literal)
{
- literal_expression_t *ret = parser_alloc(ctx, sizeof(literal_expression_t));
+ literal_expression_t *ret = new_expression(ctx, EXPR_LITERAL, sizeof(*ret));
- ret->expr.eval = literal_expression_eval;
ret->literal = literal;
return &ret->expr;
return list;
}
-static void push_func(parser_ctx_t *ctx)
-{
- func_stack_t *new_func = parser_alloc_tmp(ctx, sizeof(func_stack_t));
-
- new_func->func_head = new_func->func_tail = NULL;
- new_func->var_head = new_func->var_tail = NULL;
-
- new_func->next = ctx->func_stack;
- ctx->func_stack = new_func;
-}
-
-static source_elements_t *function_body_parsed(parser_ctx_t *ctx, source_elements_t *source)
-{
- source->functions = ctx->func_stack->func_head;
- source->variables = ctx->func_stack->var_head;
- pop_func(ctx);
-
- return source;
-}
-
static void program_parsed(parser_ctx_t *ctx, source_elements_t *source)
{
- source->functions = ctx->func_stack->func_head;
- source->variables = ctx->func_stack->var_head;
- pop_func(ctx);
-
ctx->source = source;
if(!ctx->lexer_error)
ctx->hres = S_OK;
void parser_release(parser_ctx_t *ctx)
{
- if(--ctx->ref)
- return;
-
script_release(ctx->script);
- heap_free(ctx->begin);
- jsheap_free(&ctx->heap);
+ heap_pool_free(&ctx->heap);
heap_free(ctx);
}
-HRESULT script_parse(script_ctx_t *ctx, const WCHAR *code, const WCHAR *delimiter,
+HRESULT script_parse(script_ctx_t *ctx, const WCHAR *code, const WCHAR *delimiter, BOOL from_eval,
parser_ctx_t **ret)
{
parser_ctx_t *parser_ctx;
- jsheap_t *mark;
+ heap_pool_t *mark;
HRESULT hres;
const WCHAR html_tagW[] = {'<','/','s','c','r','i','p','t','>',0};
if(!parser_ctx)
return E_OUTOFMEMORY;
- parser_ctx->ref = 1;
- parser_ctx->hres = JSCRIPT_ERROR|IDS_SYNTAX_ERROR;
+ parser_ctx->hres = JS_E_SYNTAX;
parser_ctx->is_html = delimiter && !strcmpiW(delimiter, html_tagW);
- parser_ctx->begin = heap_strdupW(code);
- if(!parser_ctx->begin) {
- heap_free(parser_ctx);
- return E_OUTOFMEMORY;
- }
-
- parser_ctx->ptr = parser_ctx->begin;
+ parser_ctx->begin = parser_ctx->ptr = code;
parser_ctx->end = parser_ctx->begin + strlenW(parser_ctx->begin);
script_addref(ctx);
parser_ctx->script = ctx;
- mark = jsheap_mark(&ctx->tmp_heap);
- jsheap_init(&parser_ctx->heap);
-
- push_func(parser_ctx);
+ mark = heap_pool_mark(&ctx->tmp_heap);
+ heap_pool_init(&parser_ctx->heap);
parser_parse(parser_ctx);
- jsheap_clear(mark);
- if(FAILED(parser_ctx->hres)) {
- hres = parser_ctx->hres;
+ heap_pool_clear(mark);
+ hres = parser_ctx->hres;
+ if(FAILED(hres)) {
+ WARN("parser failed around %s\n",
+ debugstr_w(parser_ctx->begin+20 > parser_ctx->ptr ? parser_ctx->begin : parser_ctx->ptr-20));
parser_release(parser_ctx);
return hres;
}
tShiftOper = 295,
tRelOper = 296,
tNumericLiteral = 297,
- tStringLiteral = 298,
- LOWER_THAN_ELSE = 299
+ tBooleanLiteral = 298,
+ tStringLiteral = 299,
+ tEOF = 300,
+ LOWER_THAN_ELSE = 301
};
#endif
{
/* Line 1676 of yacc.c */
-#line 150 "parser.y"
+#line 145 "parser.y"
int ival;
const WCHAR *srcptr;
/* Line 1676 of yacc.c */
-#line 119 "parser.tab.h"
+#line 121 "parser.tab.h"
} YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
#include "jscript.h"
#include "engine.h"
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(jscript);
+
#define YYLEX_PARAM ctx
#define YYPARSE_PARAM ctx
static BOOL explicit_error(parser_ctx_t*,void*,WCHAR);
static BOOL allow_auto_semicolon(parser_ctx_t*);
static void program_parsed(parser_ctx_t*,source_elements_t*);
-static source_elements_t *function_body_parsed(parser_ctx_t*,source_elements_t*);
typedef struct _statement_list_t {
statement_t *head;
static literal_t *new_string_literal(parser_ctx_t*,const WCHAR*);
static literal_t *new_null_literal(parser_ctx_t*);
-static literal_t *new_boolean_literal(parser_ctx_t*,VARIANT_BOOL);
typedef struct _property_list_t {
prop_val_t *head;
static variable_list_t *new_variable_list(parser_ctx_t*,variable_declaration_t*);
static variable_list_t *variable_list_add(parser_ctx_t*,variable_list_t*,variable_declaration_t*);
+static void *new_statement(parser_ctx_t*,statement_type_t,size_t);
static statement_t *new_block_statement(parser_ctx_t*,statement_list_t*);
static statement_t *new_var_statement(parser_ctx_t*,variable_list_t*);
-static statement_t *new_empty_statement(parser_ctx_t*);
static statement_t *new_expression_statement(parser_ctx_t*,expression_t*);
static statement_t *new_if_statement(parser_ctx_t*,expression_t*,statement_t*,statement_t*);
static statement_t *new_while_statement(parser_ctx_t*,BOOL,expression_t*,statement_t*);
static parameter_list_t *new_parameter_list(parser_ctx_t*,const WCHAR*);
static parameter_list_t *parameter_list_add(parser_ctx_t*,parameter_list_t*,const WCHAR*);
-static void push_func(parser_ctx_t*);
-static inline void pop_func(parser_ctx_t *ctx)
-{
- ctx->func_stack = ctx->func_stack->next;
-}
-
+static void *new_expression(parser_ctx_t *ctx,expression_type_t,size_t);
static expression_t *new_function_expression(parser_ctx_t*,const WCHAR*,parameter_list_t*,
source_elements_t*,const WCHAR*,DWORD);
static expression_t *new_binary_expression(parser_ctx_t*,expression_type_t,expression_t*,expression_t*);
static expression_t *new_unary_expression(parser_ctx_t*,expression_type_t,expression_t*);
static expression_t *new_conditional_expression(parser_ctx_t*,expression_t*,expression_t*,expression_t*);
-static expression_t *new_array_expression(parser_ctx_t*,expression_t*,expression_t*);
static expression_t *new_member_expression(parser_ctx_t*,expression_t*,const WCHAR*);
static expression_t *new_new_expression(parser_ctx_t*,expression_t*,argument_list_t*);
static expression_t *new_call_expression(parser_ctx_t*,expression_t*,argument_list_t*);
-static expression_t *new_this_expression(parser_ctx_t*);
static expression_t *new_identifier_expression(parser_ctx_t*,const WCHAR*);
static expression_t *new_literal_expression(parser_ctx_t*,literal_t*);
static expression_t *new_array_literal_expression(parser_ctx_t*,element_list_t*,int);
/* tokens */
%token <identifier> tIdentifier
%token <ival> tAssignOper tEqOper tShiftOper tRelOper
-%token <literal> tNumericLiteral
+%token <literal> tNumericLiteral tBooleanLiteral
%token <wstr> tStringLiteral
+%token tEOF
%type <source_elements> SourceElements
%type <source_elements> FunctionBody
/* ECMA-262 3rd Edition 14 */
Program
- : SourceElements HtmlComment
+ : SourceElements HtmlComment tEOF
{ program_parsed(ctx, $1); }
HtmlComment
{ $$ = new_function_expression(ctx, $2, $4, $7, $1, $8-$1+1); }
KFunction
- : kFUNCTION { push_func(ctx); $$ = $1; }
+ : kFUNCTION { $$ = $1; }
/* ECMA-262 3rd Edition 13 */
FunctionBody
- : SourceElements { $$ = function_body_parsed(ctx, $1); }
+ : SourceElements { $$ = $1; }
/* ECMA-262 3rd Edition 13 */
FormalParameterList
: Block { $$ = $1; }
| VariableStatement { $$ = $1; }
| EmptyStatement { $$ = $1; }
- | FunctionExpression { $$ = new_empty_statement(ctx); } /* FIXME: return NULL */
+ | FunctionExpression { $$ = new_expression_statement(ctx, $1); }
| ExpressionStatement { $$ = $1; }
| IfStatement { $$ = $1; }
| IterationStatement { $$ = $1; }
/* ECMA-262 3rd Edition 12.3 */
EmptyStatement
- : ';' { $$ = new_empty_statement(ctx); }
+ : ';' { $$ = new_statement(ctx, STAT_EMPTY, 0); }
/* ECMA-262 3rd Edition 12.4 */
ExpressionStatement
Expression_err
: Expression { $$ = $1; }
- | error { set_error(ctx, IDS_SYNTAX_ERROR); YYABORT; }
+ | error { set_error(ctx, JS_E_SYNTAX); YYABORT; }
/* ECMA-262 3rd Edition 11.14 */
Expression
: PrimaryExpression { $$ = $1; }
| FunctionExpression { $$ = $1; }
| MemberExpression '[' Expression ']'
- { $$ = new_array_expression(ctx, $1, $3); }
+ { $$ = new_binary_expression(ctx, EXPR_ARRAY, $1, $3); }
| MemberExpression '.' tIdentifier
{ $$ = new_member_expression(ctx, $1, $3); }
| kNEW MemberExpression Arguments
| CallExpression Arguments
{ $$ = new_call_expression(ctx, $1, $2); }
| CallExpression '[' Expression ']'
- { $$ = new_array_expression(ctx, $1, $3); }
+ { $$ = new_binary_expression(ctx, EXPR_ARRAY, $1, $3); }
| CallExpression '.' tIdentifier
{ $$ = new_member_expression(ctx, $1, $3); }
/* ECMA-262 3rd Edition 11.1 */
PrimaryExpression
- : kTHIS { $$ = new_this_expression(ctx); }
+ : kTHIS { $$ = new_expression(ctx, EXPR_THIS, 0); }
| tIdentifier { $$ = new_identifier_expression(ctx, $1); }
| Literal { $$ = new_literal_expression(ctx, $1); }
| ArrayLiteral { $$ = $1; }
BooleanLiteral
: kTRUE { $$ = new_boolean_literal(ctx, VARIANT_TRUE); }
| kFALSE { $$ = new_boolean_literal(ctx, VARIANT_FALSE); }
+ | tBooleanLiteral { $$ = $1; }
semicolon_opt
: ';'
left_bracket
: '('
- | error { set_error(ctx, IDS_LBRACKET); YYABORT; }
+ | error { set_error(ctx, JS_E_MISSING_LBRACKET); YYABORT; }
right_bracket
: ')'
- | error { set_error(ctx, IDS_RBRACKET); YYABORT; }
+ | error { set_error(ctx, JS_E_MISSING_RBRACKET); YYABORT; }
semicolon
: ';'
- | error { set_error(ctx, IDS_SEMICOLON); YYABORT; }
+ | error { set_error(ctx, JS_E_MISSING_SEMICOLON); YYABORT; }
%%
return ctx->nl || ctx->ptr == ctx->end || *(ctx->ptr-1) == '}';
}
-static literal_t *new_string_literal(parser_ctx_t *ctx, const WCHAR *str)
+static void *new_statement(parser_ctx_t *ctx, statement_type_t type, size_t size)
{
- literal_t *ret = parser_alloc(ctx, sizeof(literal_t));
+ statement_t *stat;
- ret->type = LT_STRING;
- ret->u.wstr = str;
+ stat = parser_alloc(ctx, size ? size : sizeof(*stat));
+ if(!stat)
+ return NULL;
- return ret;
+ stat->type = type;
+ stat->next = NULL;
+
+ return stat;
}
-static literal_t *new_null_literal(parser_ctx_t *ctx)
+static literal_t *new_string_literal(parser_ctx_t *ctx, const WCHAR *str)
{
literal_t *ret = parser_alloc(ctx, sizeof(literal_t));
- ret->type = LT_NULL;
+ ret->type = LT_STRING;
+ ret->u.wstr = str;
return ret;
}
-static literal_t *new_boolean_literal(parser_ctx_t *ctx, VARIANT_BOOL bval)
+static literal_t *new_null_literal(parser_ctx_t *ctx)
{
literal_t *ret = parser_alloc(ctx, sizeof(literal_t));
- ret->type = LT_BOOL;
- ret->u.bval = bval;
+ ret->type = LT_NULL;
return ret;
}
static statement_t *new_block_statement(parser_ctx_t *ctx, statement_list_t *list)
{
- block_statement_t *ret = parser_alloc(ctx, sizeof(block_statement_t));
+ block_statement_t *ret;
+
+ ret = new_statement(ctx, STAT_BLOCK, sizeof(*ret));
+ if(!ret)
+ return NULL;
- ret->stat.eval = block_statement_eval;
- ret->stat.next = NULL;
ret->stat_list = list ? list->head : NULL;
return &ret->stat;
static variable_declaration_t *new_variable_declaration(parser_ctx_t *ctx, const WCHAR *identifier, expression_t *expr)
{
variable_declaration_t *ret = parser_alloc(ctx, sizeof(variable_declaration_t));
- var_list_t *var_list = parser_alloc(ctx, sizeof(var_list_t));
ret->identifier = identifier;
ret->expr = expr;
ret->next = NULL;
-
- var_list->identifier = identifier;
- var_list->next = NULL;
-
- if(ctx->func_stack->var_tail)
- ctx->func_stack->var_tail = ctx->func_stack->var_tail->next = var_list;
- else
- ctx->func_stack->var_head = ctx->func_stack->var_tail = var_list;
+ ret->global_next = NULL;
return ret;
}
static statement_t *new_var_statement(parser_ctx_t *ctx, variable_list_t *variable_list)
{
- var_statement_t *ret = parser_alloc(ctx, sizeof(var_statement_t));
+ var_statement_t *ret;
+
+ ret = new_statement(ctx, STAT_VAR, sizeof(*ret));
+ if(!ret)
+ return NULL;
- ret->stat.eval = var_statement_eval;
- ret->stat.next = NULL;
ret->variable_list = variable_list->head;
return &ret->stat;
}
-static statement_t *new_empty_statement(parser_ctx_t *ctx)
-{
- statement_t *ret = parser_alloc(ctx, sizeof(statement_t));
-
- ret->eval = empty_statement_eval;
- ret->next = NULL;
-
- return ret;
-}
-
static statement_t *new_expression_statement(parser_ctx_t *ctx, expression_t *expr)
{
- expression_statement_t *ret = parser_alloc(ctx, sizeof(expression_statement_t));
+ expression_statement_t *ret;
+
+ ret = new_statement(ctx, STAT_EXPR, sizeof(*ret));
+ if(!ret)
+ return NULL;
- ret->stat.eval = expression_statement_eval;
- ret->stat.next = NULL;
ret->expr = expr;
return &ret->stat;
static statement_t *new_if_statement(parser_ctx_t *ctx, expression_t *expr, statement_t *if_stat, statement_t *else_stat)
{
- if_statement_t *ret = parser_alloc(ctx, sizeof(if_statement_t));
+ if_statement_t *ret;
+
+ ret = new_statement(ctx, STAT_IF, sizeof(*ret));
+ if(!ret)
+ return NULL;
- ret->stat.eval = if_statement_eval;
- ret->stat.next = NULL;
ret->expr = expr;
ret->if_stat = if_stat;
ret->else_stat = else_stat;
static statement_t *new_while_statement(parser_ctx_t *ctx, BOOL dowhile, expression_t *expr, statement_t *stat)
{
- while_statement_t *ret = parser_alloc(ctx, sizeof(while_statement_t));
+ while_statement_t *ret;
+
+ ret = new_statement(ctx, STAT_WHILE, sizeof(*ret));
+ if(!ret)
+ return NULL;
- ret->stat.eval = while_statement_eval;
- ret->stat.next = NULL;
ret->do_while = dowhile;
ret->expr = expr;
ret->statement = stat;
static statement_t *new_for_statement(parser_ctx_t *ctx, variable_list_t *variable_list, expression_t *begin_expr,
expression_t *expr, expression_t *end_expr, statement_t *statement)
{
- for_statement_t *ret = parser_alloc(ctx, sizeof(for_statement_t));
+ for_statement_t *ret;
+
+ ret = new_statement(ctx, STAT_FOR, sizeof(*ret));
+ if(!ret)
+ return NULL;
- ret->stat.eval = for_statement_eval;
- ret->stat.next = NULL;
ret->variable_list = variable_list ? variable_list->head : NULL;
ret->begin_expr = begin_expr;
ret->expr = expr;
static statement_t *new_forin_statement(parser_ctx_t *ctx, variable_declaration_t *variable, expression_t *expr,
expression_t *in_expr, statement_t *statement)
{
- forin_statement_t *ret = parser_alloc(ctx, sizeof(forin_statement_t));
+ forin_statement_t *ret;
+
+ ret = new_statement(ctx, STAT_FORIN, sizeof(*ret));
+ if(!ret)
+ return NULL;
- ret->stat.eval = forin_statement_eval;
- ret->stat.next = NULL;
ret->variable = variable;
ret->expr = expr;
ret->in_expr = in_expr;
static statement_t *new_continue_statement(parser_ctx_t *ctx, const WCHAR *identifier)
{
- branch_statement_t *ret = parser_alloc(ctx, sizeof(branch_statement_t));
+ branch_statement_t *ret;
+
+ ret = new_statement(ctx, STAT_CONTINUE, sizeof(*ret));
+ if(!ret)
+ return NULL;
- ret->stat.eval = continue_statement_eval;
- ret->stat.next = NULL;
ret->identifier = identifier;
return &ret->stat;
static statement_t *new_break_statement(parser_ctx_t *ctx, const WCHAR *identifier)
{
- branch_statement_t *ret = parser_alloc(ctx, sizeof(branch_statement_t));
+ branch_statement_t *ret;
+
+ ret = new_statement(ctx, STAT_BREAK, sizeof(*ret));
+ if(!ret)
+ return NULL;
- ret->stat.eval = break_statement_eval;
- ret->stat.next = NULL;
ret->identifier = identifier;
return &ret->stat;
static statement_t *new_return_statement(parser_ctx_t *ctx, expression_t *expr)
{
- expression_statement_t *ret = parser_alloc(ctx, sizeof(expression_statement_t));
+ expression_statement_t *ret;
+
+ ret = new_statement(ctx, STAT_RETURN, sizeof(*ret));
+ if(!ret)
+ return NULL;
- ret->stat.eval = return_statement_eval;
- ret->stat.next = NULL;
ret->expr = expr;
return &ret->stat;
static statement_t *new_with_statement(parser_ctx_t *ctx, expression_t *expr, statement_t *statement)
{
- with_statement_t *ret = parser_alloc(ctx, sizeof(with_statement_t));
+ with_statement_t *ret;
+
+ ret = new_statement(ctx, STAT_WITH, sizeof(*ret));
+ if(!ret)
+ return NULL;
- ret->stat.eval = with_statement_eval;
- ret->stat.next = NULL;
ret->expr = expr;
ret->statement = statement;
static statement_t *new_labelled_statement(parser_ctx_t *ctx, const WCHAR *identifier, statement_t *statement)
{
- labelled_statement_t *ret = parser_alloc(ctx, sizeof(labelled_statement_t));
+ labelled_statement_t *ret;
+
+ ret = new_statement(ctx, STAT_LABEL, sizeof(*ret));
+ if(!ret)
+ return NULL;
- ret->stat.eval = labelled_statement_eval;
- ret->stat.next = NULL;
ret->identifier = identifier;
ret->statement = statement;
static statement_t *new_switch_statement(parser_ctx_t *ctx, expression_t *expr, case_clausule_t *case_list)
{
- switch_statement_t *ret = parser_alloc(ctx, sizeof(switch_statement_t));
+ switch_statement_t *ret;
+
+ ret = new_statement(ctx, STAT_SWITCH, sizeof(*ret));
+ if(!ret)
+ return NULL;
- ret->stat.eval = switch_statement_eval;
- ret->stat.next = NULL;
ret->expr = expr;
ret->case_list = case_list;
static statement_t *new_throw_statement(parser_ctx_t *ctx, expression_t *expr)
{
- expression_statement_t *ret = parser_alloc(ctx, sizeof(expression_statement_t));
+ expression_statement_t *ret;
+
+ ret = new_statement(ctx, STAT_THROW, sizeof(*ret));
+ if(!ret)
+ return NULL;
- ret->stat.eval = throw_statement_eval;
- ret->stat.next = NULL;
ret->expr = expr;
return &ret->stat;
static statement_t *new_try_statement(parser_ctx_t *ctx, statement_t *try_statement,
catch_block_t *catch_block, statement_t *finally_statement)
{
- try_statement_t *ret = parser_alloc(ctx, sizeof(try_statement_t));
+ try_statement_t *ret;
+
+ ret = new_statement(ctx, STAT_TRY, sizeof(*ret));
+ if(!ret)
+ return NULL;
- ret->stat.eval = try_statement_eval;
- ret->stat.next = NULL;
ret->try_statement = try_statement;
ret->catch_block = catch_block;
ret->finally_statement = finally_statement;
static expression_t *new_function_expression(parser_ctx_t *ctx, const WCHAR *identifier,
parameter_list_t *parameter_list, source_elements_t *source_elements, const WCHAR *src_str, DWORD src_len)
{
- function_expression_t *ret = parser_alloc(ctx, sizeof(function_expression_t));
+ function_expression_t *ret = new_expression(ctx, EXPR_FUNC, sizeof(*ret));
- ret->expr.eval = function_expression_eval;
ret->identifier = identifier;
ret->parameter_list = parameter_list ? parameter_list->head : NULL;
ret->source_elements = source_elements;
ret->src_str = src_str;
ret->src_len = src_len;
+ ret->next = NULL;
- if(ret->identifier) {
- function_declaration_t *decl = parser_alloc(ctx, sizeof(function_declaration_t));
+ return &ret->expr;
+}
- decl->expr = ret;
- decl->next = NULL;
+static void *new_expression(parser_ctx_t *ctx, expression_type_t type, size_t size)
+{
+ expression_t *ret = parser_alloc(ctx, size ? size : sizeof(*ret));
- if(ctx->func_stack->func_tail)
- ctx->func_stack->func_tail = ctx->func_stack->func_tail->next = decl;
- else
- ctx->func_stack->func_head = ctx->func_stack->func_tail = decl;
- }
+ ret->type = type;
- return &ret->expr;
+ return ret;
}
-static const expression_eval_t expression_eval_table[] = {
- comma_expression_eval,
- logical_or_expression_eval,
- logical_and_expression_eval,
- binary_or_expression_eval,
- binary_xor_expression_eval,
- binary_and_expression_eval,
- instanceof_expression_eval,
- in_expression_eval,
- add_expression_eval,
- sub_expression_eval,
- mul_expression_eval,
- div_expression_eval,
- mod_expression_eval,
- delete_expression_eval,
- void_expression_eval,
- typeof_expression_eval,
- minus_expression_eval,
- plus_expression_eval,
- post_increment_expression_eval,
- post_decrement_expression_eval,
- pre_increment_expression_eval,
- pre_decrement_expression_eval,
- equal_expression_eval,
- equal2_expression_eval,
- not_equal_expression_eval,
- not_equal2_expression_eval,
- less_expression_eval,
- lesseq_expression_eval,
- greater_expression_eval,
- greatereq_expression_eval,
- binary_negation_expression_eval,
- logical_negation_expression_eval,
- left_shift_expression_eval,
- right_shift_expression_eval,
- right2_shift_expression_eval,
- assign_expression_eval,
- assign_lshift_expression_eval,
- assign_rshift_expression_eval,
- assign_rrshift_expression_eval,
- assign_add_expression_eval,
- assign_sub_expression_eval,
- assign_mul_expression_eval,
- assign_div_expression_eval,
- assign_mod_expression_eval,
- assign_and_expression_eval,
- assign_or_expression_eval,
- assign_xor_expression_eval,
-};
-
static expression_t *new_binary_expression(parser_ctx_t *ctx, expression_type_t type,
expression_t *expression1, expression_t *expression2)
{
- binary_expression_t *ret = parser_alloc(ctx, sizeof(binary_expression_t));
+ binary_expression_t *ret = new_expression(ctx, type, sizeof(*ret));
- ret->expr.eval = expression_eval_table[type];
ret->expression1 = expression1;
ret->expression2 = expression2;
static expression_t *new_unary_expression(parser_ctx_t *ctx, expression_type_t type, expression_t *expression)
{
- unary_expression_t *ret = parser_alloc(ctx, sizeof(unary_expression_t));
+ unary_expression_t *ret = new_expression(ctx, type, sizeof(*ret));
- ret->expr.eval = expression_eval_table[type];
ret->expression = expression;
return &ret->expr;
static expression_t *new_conditional_expression(parser_ctx_t *ctx, expression_t *expression,
expression_t *true_expression, expression_t *false_expression)
{
- conditional_expression_t *ret = parser_alloc(ctx, sizeof(conditional_expression_t));
+ conditional_expression_t *ret = new_expression(ctx, EXPR_COND, sizeof(*ret));
- ret->expr.eval = conditional_expression_eval;
ret->expression = expression;
ret->true_expression = true_expression;
ret->false_expression = false_expression;
return &ret->expr;
}
-static expression_t *new_array_expression(parser_ctx_t *ctx, expression_t *member_expr, expression_t *expression)
-{
- array_expression_t *ret = parser_alloc(ctx, sizeof(array_expression_t));
-
- ret->expr.eval = array_expression_eval;
- ret->member_expr = member_expr;
- ret->expression = expression;
-
- return &ret->expr;
-}
-
static expression_t *new_member_expression(parser_ctx_t *ctx, expression_t *expression, const WCHAR *identifier)
{
- member_expression_t *ret = parser_alloc(ctx, sizeof(member_expression_t));
+ member_expression_t *ret = new_expression(ctx, EXPR_MEMBER, sizeof(*ret));
- ret->expr.eval = member_expression_eval;
ret->expression = expression;
ret->identifier = identifier;
static expression_t *new_new_expression(parser_ctx_t *ctx, expression_t *expression, argument_list_t *argument_list)
{
- call_expression_t *ret = parser_alloc(ctx, sizeof(call_expression_t));
+ call_expression_t *ret = new_expression(ctx, EXPR_NEW, sizeof(*ret));
- ret->expr.eval = new_expression_eval;
ret->expression = expression;
ret->argument_list = argument_list ? argument_list->head : NULL;
static expression_t *new_call_expression(parser_ctx_t *ctx, expression_t *expression, argument_list_t *argument_list)
{
- call_expression_t *ret = parser_alloc(ctx, sizeof(call_expression_t));
+ call_expression_t *ret = new_expression(ctx, EXPR_CALL, sizeof(*ret));
- ret->expr.eval = call_expression_eval;
ret->expression = expression;
ret->argument_list = argument_list ? argument_list->head : NULL;
return &ret->expr;
}
-static expression_t *new_this_expression(parser_ctx_t *ctx)
-{
- expression_t *ret = parser_alloc(ctx, sizeof(expression_t));
-
- ret->eval = this_expression_eval;
-
- return ret;
-}
-
static int parser_error(const char *str)
{
return 0;
static void set_error(parser_ctx_t *ctx, UINT error)
{
- ctx->hres = JSCRIPT_ERROR|error;
+ ctx->hres = error;
}
static BOOL explicit_error(parser_ctx_t *ctx, void *obj, WCHAR next)
{
if(obj || *(ctx->ptr-1)==next) return TRUE;
- set_error(ctx, IDS_SYNTAX_ERROR);
+ set_error(ctx, JS_E_SYNTAX);
return FALSE;
}
static expression_t *new_identifier_expression(parser_ctx_t *ctx, const WCHAR *identifier)
{
- identifier_expression_t *ret = parser_alloc(ctx, sizeof(identifier_expression_t));
+ identifier_expression_t *ret = new_expression(ctx, EXPR_IDENT, sizeof(*ret));
- ret->expr.eval = identifier_expression_eval;
ret->identifier = identifier;
return &ret->expr;
static expression_t *new_array_literal_expression(parser_ctx_t *ctx, element_list_t *element_list, int length)
{
- array_literal_expression_t *ret = parser_alloc(ctx, sizeof(array_literal_expression_t));
+ array_literal_expression_t *ret = new_expression(ctx, EXPR_ARRAYLIT, sizeof(*ret));
- ret->expr.eval = array_literal_expression_eval;
ret->element_list = element_list ? element_list->head : NULL;
ret->length = length;
static expression_t *new_prop_and_value_expression(parser_ctx_t *ctx, property_list_t *property_list)
{
- property_value_expression_t *ret = parser_alloc(ctx, sizeof(property_value_expression_t));
+ property_value_expression_t *ret = new_expression(ctx, EXPR_PROPVAL, sizeof(*ret));
- ret->expr.eval = property_value_expression_eval;
ret->property_list = property_list ? property_list->head : NULL;
return &ret->expr;
static expression_t *new_literal_expression(parser_ctx_t *ctx, literal_t *literal)
{
- literal_expression_t *ret = parser_alloc(ctx, sizeof(literal_expression_t));
+ literal_expression_t *ret = new_expression(ctx, EXPR_LITERAL, sizeof(*ret));
- ret->expr.eval = literal_expression_eval;
ret->literal = literal;
return &ret->expr;
return list;
}
-static void push_func(parser_ctx_t *ctx)
-{
- func_stack_t *new_func = parser_alloc_tmp(ctx, sizeof(func_stack_t));
-
- new_func->func_head = new_func->func_tail = NULL;
- new_func->var_head = new_func->var_tail = NULL;
-
- new_func->next = ctx->func_stack;
- ctx->func_stack = new_func;
-}
-
-static source_elements_t *function_body_parsed(parser_ctx_t *ctx, source_elements_t *source)
-{
- source->functions = ctx->func_stack->func_head;
- source->variables = ctx->func_stack->var_head;
- pop_func(ctx);
-
- return source;
-}
-
static void program_parsed(parser_ctx_t *ctx, source_elements_t *source)
{
- source->functions = ctx->func_stack->func_head;
- source->variables = ctx->func_stack->var_head;
- pop_func(ctx);
-
ctx->source = source;
if(!ctx->lexer_error)
ctx->hres = S_OK;
void parser_release(parser_ctx_t *ctx)
{
- if(--ctx->ref)
- return;
-
script_release(ctx->script);
- heap_free(ctx->begin);
- jsheap_free(&ctx->heap);
+ heap_pool_free(&ctx->heap);
heap_free(ctx);
}
-HRESULT script_parse(script_ctx_t *ctx, const WCHAR *code, const WCHAR *delimiter,
+HRESULT script_parse(script_ctx_t *ctx, const WCHAR *code, const WCHAR *delimiter, BOOL from_eval,
parser_ctx_t **ret)
{
parser_ctx_t *parser_ctx;
- jsheap_t *mark;
+ heap_pool_t *mark;
HRESULT hres;
const WCHAR html_tagW[] = {'<','/','s','c','r','i','p','t','>',0};
if(!parser_ctx)
return E_OUTOFMEMORY;
- parser_ctx->ref = 1;
- parser_ctx->hres = JSCRIPT_ERROR|IDS_SYNTAX_ERROR;
+ parser_ctx->hres = JS_E_SYNTAX;
parser_ctx->is_html = delimiter && !strcmpiW(delimiter, html_tagW);
- parser_ctx->begin = heap_strdupW(code);
- if(!parser_ctx->begin) {
- heap_free(parser_ctx);
- return E_OUTOFMEMORY;
- }
-
- parser_ctx->ptr = parser_ctx->begin;
+ parser_ctx->begin = parser_ctx->ptr = code;
parser_ctx->end = parser_ctx->begin + strlenW(parser_ctx->begin);
script_addref(ctx);
parser_ctx->script = ctx;
- mark = jsheap_mark(&ctx->tmp_heap);
- jsheap_init(&parser_ctx->heap);
-
- push_func(parser_ctx);
+ mark = heap_pool_mark(&ctx->tmp_heap);
+ heap_pool_init(&parser_ctx->heap);
parser_parse(parser_ctx);
- jsheap_clear(mark);
- if(FAILED(parser_ctx->hres)) {
- hres = parser_ctx->hres;
+ heap_pool_clear(mark);
+ hres = parser_ctx->hres;
+ if(FAILED(hres)) {
+ WARN("parser failed around %s\n",
+ debugstr_w(parser_ctx->begin+20 > parser_ctx->ptr ? parser_ctx->begin : parser_ctx->ptr-20));
parser_release(parser_ctx);
return hres;
}
*/
#include <assert.h>
-#include <math.h>
#include "jscript.h"
+#include "regexp.h"
#include <wine/debug.h>
WINE_DEFAULT_DEBUG_CHANNEL(jscript);
-#define JSREG_FOLD 0x01 /* fold uppercase to lowercase */
-#define JSREG_GLOB 0x02 /* global exec, creates array of matches */
-#define JSREG_MULTILINE 0x04 /* treat ^ and $ as begin and end of line */
-#define JSREG_STICKY 0x08 /* only match starting at lastIndex */
+/* FIXME: Better error handling */
+#define ReportRegExpError(a,b,c)
+#define ReportRegExpErrorHelper(a,b,c,d)
+#define JS_ReportErrorNumber(a,b,c,d)
+#define JS_ReportErrorFlagsAndNumber(a,b,c,d,e,f)
+#define js_ReportOutOfScriptQuota(a)
+#define JS_ReportOutOfMemory(a)
+#define JS_COUNT_OPERATION(a,b)
+
typedef BYTE JSPackedBool;
-typedef BYTE jsbytecode;
/*
* This struct holds a bitmap representation of a class from a regexp.
- * There's a list of these referenced by the classList field in the JSRegExp
+ * There's a list of these referenced by the classList field in the regexp_t
* struct below. The initial state has startIndex set to the offset in the
* original regexp source of the beginning of the class contents. The first
* use of the class converts the source representation into a bitmap.
} u;
} RECharSet;
-typedef struct {
- WORD flags; /* flags, see jsapi.h's JSREG_* defines */
- size_t parenCount; /* number of parenthesized submatches */
- size_t classCount; /* count [...] bitmaps */
- RECharSet *classList; /* list of [...] bitmaps */
- BSTR source; /* locked source string, sans // */
- jsbytecode program[1]; /* regular expression bytecode */
-} JSRegExp;
-
-typedef struct {
- DispatchEx dispex;
-
- JSRegExp *jsregexp;
- BSTR str;
- INT last_index;
- VARIANT last_index_var;
-} RegExpInstance;
-
-static const WCHAR sourceW[] = {'s','o','u','r','c','e',0};
-static const WCHAR globalW[] = {'g','l','o','b','a','l',0};
-static const WCHAR ignoreCaseW[] = {'i','g','n','o','r','e','C','a','s','e',0};
-static const WCHAR multilineW[] = {'m','u','l','t','i','l','i','n','e',0};
-static const WCHAR lastIndexW[] = {'l','a','s','t','I','n','d','e','x',0};
-static const WCHAR toStringW[] = {'t','o','S','t','r','i','n','g',0};
-static const WCHAR execW[] = {'e','x','e','c',0};
-static const WCHAR testW[] = {'t','e','s','t',0};
-
-static const WCHAR leftContextW[] =
- {'l','e','f','t','C','o','n','t','e','x','t',0};
-static const WCHAR rightContextW[] =
- {'r','i','g','h','t','C','o','n','t','e','x','t',0};
-
-static const WCHAR undefinedW[] = {'u','n','d','e','f','i','n','e','d',0};
-static const WCHAR emptyW[] = {0};
-
-/* FIXME: Better error handling */
-#define ReportRegExpError(a,b,c)
-#define ReportRegExpErrorHelper(a,b,c,d)
-#define JS_ReportErrorNumber(a,b,c,d)
-#define JS_ReportErrorFlagsAndNumber(a,b,c,d,e,f)
-#define js_ReportOutOfScriptQuota(a)
-#define JS_ReportOutOfMemory(a)
-#define JS_COUNT_OPERATION(a,b)
-
#define JSMSG_MIN_TOO_BIG 47
#define JSMSG_MAX_TOO_BIG 48
#define JSMSG_OUT_OF_ORDER 49
NULL
};
-typedef struct RECapture {
- ptrdiff_t index; /* start of contents, -1 for empty */
- size_t length; /* length of capture */
-} RECapture;
-
-typedef struct REMatchState {
- const WCHAR *cp;
- RECapture parens[1]; /* first of 're->parenCount' captures,
- allocated at end of this struct */
-} REMatchState;
-
typedef struct REProgState {
jsbytecode *continue_pc; /* current continuation data */
jsbytecode continue_op;
#define INITIAL_BACKTRACK 8000
typedef struct REGlobalData {
- script_ctx_t *cx;
- JSRegExp *regexp; /* the RE in execution */
+ void *cx;
+ regexp_t *regexp; /* the RE in execution */
BOOL ok; /* runtime error (out_of_memory only?) */
size_t start; /* offset to start at */
ptrdiff_t skipped; /* chars skipped anchoring this r.e. */
size_t backTrackCount; /* how many times we've backtracked */
size_t backTrackLimit; /* upper limit on backtrack states */
- jsheap_t *pool; /* It's faster to use one malloc'd pool
+ heap_pool_t *pool; /* It's faster to use one malloc'd pool
than to malloc/free the three items
that are allocated from this pool */
} REGlobalData;
#define CLASS_CACHE_SIZE 4
typedef struct CompilerState {
- script_ctx_t *context;
+ void *context;
const WCHAR *cpbegin;
const WCHAR *cpend;
const WCHAR *cp;
size_t index;
} classCache[CLASS_CACHE_SIZE];
WORD flags;
+
+ heap_pool_t *pool; /* It's faster to use one malloc'd pool
+ than to malloc/free */
} CompilerState;
typedef struct EmitStateStackEntry {
{
RENode *ren;
- ren = jsheap_alloc(&state->context->tmp_heap, sizeof(*ren));
+ ren = heap_pool_alloc(state->pool, sizeof(*ren));
if (!ren) {
/* js_ReportOutOfScriptQuota(cx); */
return NULL;
* of recursion.
*/
static jsbytecode *
-EmitREBytecode(CompilerState *state, JSRegExp *re, size_t treeDepth,
+EmitREBytecode(CompilerState *state, regexp_t *re, size_t treeDepth,
jsbytecode *pc, RENode *t)
{
EmitStateStackEntry *emitStateSP, *emitStateStack;
}
}
if (t->kid && t->u.flat.length > 1) {
- pc[-1] = (state->flags & JSREG_FOLD) ? REOP_FLATi : REOP_FLAT;
+ pc[-1] = (state->flags & REG_FOLD) ? REOP_FLATi : REOP_FLAT;
pc = WriteCompactIndex(pc, (WCHAR*)t->kid - state->cpbegin);
pc = WriteCompactIndex(pc, t->u.flat.length);
} else if (t->u.flat.chr < 256) {
- pc[-1] = (state->flags & JSREG_FOLD) ? REOP_FLAT1i : REOP_FLAT1;
+ pc[-1] = (state->flags & REG_FOLD) ? REOP_FLAT1i : REOP_FLAT1;
*pc++ = (jsbytecode) t->u.flat.chr;
} else {
- pc[-1] = (state->flags & JSREG_FOLD)
+ pc[-1] = (state->flags & REG_FOLD)
? REOP_UCFLAT1i
: REOP_UCFLAT1;
SET_ARG(pc, t->u.flat.chr);
*/
if (((RENode *) result->kid)->op == REOP_FLAT &&
((RENode *) result->u.kid2)->op == REOP_FLAT &&
- (state->flags & JSREG_FOLD) == 0) {
+ (state->flags & REG_FOLD) == 0) {
result->op = REOP_ALTPREREQ;
result->u.altprereq.ch1 = ((RENode *) result->kid)->u.flat.chr;
result->u.altprereq.ch2 = ((RENode *) result->u.kid2)->u.flat.chr;
if (((RENode *) result->kid)->op == REOP_CLASS &&
((RENode *) result->kid)->u.ucclass.index < 256 &&
((RENode *) result->u.kid2)->op == REOP_FLAT &&
- (state->flags & JSREG_FOLD) == 0) {
+ (state->flags & REG_FOLD) == 0) {
result->op = REOP_ALTPREREQ2;
result->u.altprereq.ch1 = ((RENode *) result->u.kid2)->u.flat.chr;
result->u.altprereq.ch2 = ((RENode *) result->kid)->u.ucclass.index;
if (((RENode *) result->kid)->op == REOP_FLAT &&
((RENode *) result->u.kid2)->op == REOP_CLASS &&
((RENode *) result->u.kid2)->u.ucclass.index < 256 &&
- (state->flags & JSREG_FOLD) == 0) {
+ (state->flags & REG_FOLD) == 0) {
result->op = REOP_ALTPREREQ2;
result->u.altprereq.ch1 = ((RENode *) result->kid)->u.flat.chr;
result->u.altprereq.ch2 =
continue;
}
}
- if (state->flags & JSREG_FOLD)
+ if (state->flags & REG_FOLD)
rangeStart = localMax; /* one run of the uc/dc loop below */
}
- if (state->flags & JSREG_FOLD) {
+ if (state->flags & REG_FOLD) {
WCHAR maxch = localMax;
for (i = rangeStart; i <= localMax; i++) {
*/
static REBackTrackData *
PushBackTrackState(REGlobalData *gData, REOp op,
- jsbytecode *target, REMatchState *x, const WCHAR *cp,
+ jsbytecode *target, match_state_t *x, const WCHAR *cp,
size_t parenIndex, size_t parenCount)
{
size_t i;
JS_COUNT_OPERATION(gData->cx, JSOW_ALLOCATION);
btincr = ((btincr+btsize-1)/btsize)*btsize;
- gData->backTrackStack = jsheap_grow(gData->pool, gData->backTrackStack, btsize, btincr);
+ gData->backTrackStack = heap_pool_grow(gData->pool, gData->backTrackStack, btsize, btincr);
if (!gData->backTrackStack) {
js_ReportOutOfScriptQuota(gData->cx);
gData->ok = FALSE;
return result;
}
-static inline REMatchState *
-FlatNIMatcher(REGlobalData *gData, REMatchState *x, WCHAR *matchChars,
+static inline match_state_t *
+FlatNIMatcher(REGlobalData *gData, match_state_t *x, const WCHAR *matchChars,
size_t length)
{
size_t i;
* 9. Let y be the State (f, cap).
* 10. Call c(y) and return its result.
*/
-static REMatchState *
-BackrefMatcher(REGlobalData *gData, REMatchState *x, size_t parenIndex)
+static match_state_t *
+BackrefMatcher(REGlobalData *gData, match_state_t *x, size_t parenIndex)
{
size_t len, i;
const WCHAR *parenContent;
return NULL;
parenContent = &gData->cpbegin[cap->index];
- if (gData->regexp->flags & JSREG_FOLD) {
+ if (gData->regexp->flags & REG_FOLD) {
for (i = 0; i < len; i++) {
if (toupperW(parenContent[i]) != toupperW(x->cp[i]))
return NULL;
* source string.
*/
assert(1 <= charSet->u.src.startIndex);
- assert(charSet->u.src.startIndex
- < SysStringLen(gData->regexp->source));
- assert(charSet->u.src.length <= SysStringLen(gData->regexp->source)
- - 1 - charSet->u.src.startIndex);
+ assert(charSet->u.src.startIndex < gData->regexp->source_len);
+ assert(charSet->u.src.length <= gData->regexp->source_len
+ - 1 - charSet->u.src.startIndex);
charSet->converted = TRUE;
src = gData->regexp->source + charSet->u.src.startIndex;
}
if (inRange) {
- if (gData->regexp->flags & JSREG_FOLD) {
- int i;
-
+ if (gData->regexp->flags & REG_FOLD) {
assert(rangeStart <= thisCh);
for (i = rangeStart; i <= thisCh; i++) {
WCHAR uch, dch;
}
inRange = FALSE;
} else {
- if (gData->regexp->flags & JSREG_FOLD) {
+ if (gData->regexp->flags & REG_FOLD) {
AddCharacterToCharSet(charSet, toupperW(thisCh));
AddCharacterToCharSet(charSet, tolowerW(thisCh));
} else {
size_t limit = gData->stateStackLimit;
size_t sz = sizeof(REProgState) * limit;
- gData->stateStack = jsheap_grow(gData->pool, gData->stateStack, sz, sz);
+ gData->stateStack = heap_pool_grow(gData->pool, gData->stateStack, sz, sz);
if (!gData->stateStack) {
js_ReportOutOfScriptQuota(gData->cx);
gData->ok = FALSE;
* true, then update the current state's cp. Always update startpc to the next
* op.
*/
-static inline REMatchState *
-SimpleMatch(REGlobalData *gData, REMatchState *x, REOp op,
+static inline match_state_t *
+SimpleMatch(REGlobalData *gData, match_state_t *x, REOp op,
jsbytecode **startpc, BOOL updatecp)
{
- REMatchState *result = NULL;
+ match_state_t *result = NULL;
WCHAR matchCh;
size_t parenIndex;
size_t offset, length, index;
jsbytecode *pc = *startpc; /* pc has already been incremented past op */
- WCHAR *source;
+ const WCHAR *source;
const WCHAR *startcp = x->cp;
WCHAR ch;
RECharSet *charSet;
case REOP_BOL:
if (x->cp != gData->cpbegin) {
if (/*!gData->cx->regExpStatics.multiline && FIXME !!! */
- !(gData->regexp->flags & JSREG_MULTILINE)) {
+ !(gData->regexp->flags & REG_MULTILINE)) {
break;
}
if (!RE_IS_LINE_TERM(x->cp[-1]))
case REOP_EOL:
if (x->cp != gData->cpend) {
if (/*!gData->cx->regExpStatics.multiline &&*/
- !(gData->regexp->flags & JSREG_MULTILINE)) {
+ !(gData->regexp->flags & REG_MULTILINE)) {
break;
}
if (!RE_IS_LINE_TERM(*x->cp))
break;
case REOP_FLAT:
pc = ReadCompactIndex(pc, &offset);
- assert(offset < SysStringLen(gData->regexp->source));
+ assert(offset < gData->regexp->source_len);
pc = ReadCompactIndex(pc, &length);
assert(1 <= length);
- assert(length <= SysStringLen(gData->regexp->source) - offset);
+ assert(length <= gData->regexp->source_len - offset);
if (length <= (size_t)(gData->cpend - x->cp)) {
source = gData->regexp->source + offset;
TRACE("%s\n", debugstr_wn(source, length));
break;
case REOP_FLATi:
pc = ReadCompactIndex(pc, &offset);
- assert(offset < SysStringLen(gData->regexp->source));
+ assert(offset < gData->regexp->source_len);
pc = ReadCompactIndex(pc, &length);
assert(1 <= length);
- assert(length <= SysStringLen(gData->regexp->source) - offset);
+ assert(length <= gData->regexp->source_len - offset);
source = gData->regexp->source;
result = FlatNIMatcher(gData, x, source + offset, length);
break;
return NULL;
}
-static inline REMatchState *
-ExecuteREBytecode(REGlobalData *gData, REMatchState *x)
+static inline match_state_t *
+ExecuteREBytecode(REGlobalData *gData, match_state_t *x)
{
- REMatchState *result = NULL;
+ match_state_t *result = NULL;
REBackTrackData *backTrackData;
jsbytecode *nextpc, *testpc;
REOp nextop;
* If the first node is a simple match, step the index into the string
* until that match is made, or fail if it can't be found at all.
*/
- if (REOP_IS_SIMPLE(op) && !(gData->regexp->flags & JSREG_STICKY)) {
+ if (REOP_IS_SIMPLE(op) && !(gData->regexp->flags & REG_STICKY)) {
anchor = FALSE;
while (x->cp <= gData->cpend) {
nextpc = pc; /* reset back to start each time */
result = NULL;
break;
}
- /* else false thru... */
+ /* else fall through... */
case REOP_ALT:
doAlt:
TRACE("{%d,%d}\n", curState->u.quantifier.min, curState->u.quantifier.max);
#define PREPARE_REPEAT() \
do { \
- curState->index = x->cp - gData->cpbegin; \
+ curState->index = x->cp - gData->cpbegin; \
curState->continue_op = REOP_MINIMALREPEAT; \
curState->continue_pc = pc; \
pc += ARG_LEN; \
return x;
}
-static REMatchState *MatchRegExp(REGlobalData *gData, REMatchState *x)
+static match_state_t *MatchRegExp(REGlobalData *gData, match_state_t *x)
{
- REMatchState *result;
+ match_state_t *result;
const WCHAR *cp = x->cp;
const WCHAR *cp2;
UINT j;
for (j = 0; j < gData->regexp->parenCount; j++)
x->parens[j].index = -1;
result = ExecuteREBytecode(gData, x);
- if (!gData->ok || result || (gData->regexp->flags & JSREG_STICKY))
+ if (!gData->ok || result || (gData->regexp->flags & REG_STICKY))
return result;
gData->backTrackSP = gData->backTrackStack;
gData->cursz = 0;
return NULL;
}
-#define MIN_BACKTRACK_LIMIT 400000
-
-static REMatchState *InitMatch(script_ctx_t *cx, REGlobalData *gData, JSRegExp *re, size_t length)
+static HRESULT InitMatch(regexp_t *re, void *cx, heap_pool_t *pool, REGlobalData *gData)
{
- REMatchState *result;
UINT i;
gData->backTrackStackSize = INITIAL_BACKTRACK;
- gData->backTrackStack = jsheap_alloc(gData->pool, INITIAL_BACKTRACK);
+ gData->backTrackStack = heap_pool_alloc(gData->pool, INITIAL_BACKTRACK);
if (!gData->backTrackStack)
goto bad;
gData->backTrackLimit = 0;
gData->stateStackLimit = INITIAL_STATESTACK;
- gData->stateStack = jsheap_alloc(gData->pool, sizeof(REProgState) * INITIAL_STATESTACK);
+ gData->stateStack = heap_pool_alloc(gData->pool, sizeof(REProgState) * INITIAL_STATESTACK);
if (!gData->stateStack)
goto bad;
gData->stateStackTop = 0;
gData->cx = cx;
+ gData->pool = pool;
gData->regexp = re;
gData->ok = TRUE;
- result = jsheap_alloc(gData->pool, offsetof(REMatchState, parens) + re->parenCount * sizeof(RECapture));
- if (!result)
- goto bad;
-
for (i = 0; i < re->classCount; i++) {
if (!re->classList[i].converted &&
- !ProcessCharSet(gData, &re->classList[i])) {
- return NULL;
+ !ProcessCharSet(gData, &re->classList[i])) {
+ return E_FAIL;
}
}
- return result;
+ return S_OK;
bad:
js_ReportOutOfScriptQuota(cx);
gData->ok = FALSE;
- return NULL;
+ return E_OUTOFMEMORY;
}
-static void
-js_DestroyRegExp(JSRegExp *re)
+HRESULT regexp_execute(regexp_t *regexp, void *cx, heap_pool_t *pool,
+ const WCHAR *str, DWORD str_len, match_state_t *result)
+{
+ match_state_t *res;
+ REGlobalData gData;
+ heap_pool_t *mark = heap_pool_mark(pool);
+ const WCHAR *str_beg = result->cp;
+ HRESULT hres;
+
+ assert(result->cp != NULL);
+
+ gData.cpbegin = str;
+ gData.cpend = str+str_len;
+ gData.start = result->cp-str;
+ gData.skipped = 0;
+ gData.pool = pool;
+
+ hres = InitMatch(regexp, cx, pool, &gData);
+ if(FAILED(hres)) {
+ WARN("InitMatch failed\n");
+ heap_pool_clear(mark);
+ return hres;
+ }
+
+ res = MatchRegExp(&gData, result);
+ heap_pool_clear(mark);
+ if(!gData.ok) {
+ WARN("MatchRegExp failed\n");
+ return E_FAIL;
+ }
+
+ if(!res) {
+ result->match_len = 0;
+ return S_FALSE;
+ }
+
+ result->match_len = (result->cp-str_beg) - gData.skipped;
+ result->paren_count = regexp->parenCount;
+ return S_OK;
+}
+
+void regexp_destroy(regexp_t *re)
{
if (re->classList) {
UINT i;
heap_free(re);
}
-static JSRegExp *
-js_NewRegExp(script_ctx_t *cx, BSTR str, UINT flags, BOOL flat)
+regexp_t* regexp_new(void *cx, heap_pool_t *pool, const WCHAR *str,
+ DWORD str_len, WORD flags, BOOL flat)
{
- JSRegExp *re;
- jsheap_t *mark;
+ regexp_t *re;
+ heap_pool_t *mark;
CompilerState state;
size_t resize;
jsbytecode *endPC;
size_t len;
re = NULL;
- mark = jsheap_mark(&cx->tmp_heap);
- len = SysStringLen(str);
+ mark = heap_pool_mark(pool);
+ len = str_len;
state.context = cx;
+ state.pool = pool;
state.cp = str;
if (!state.cp)
goto out;
if (!ParseRegExp(&state))
goto out;
}
- resize = offsetof(JSRegExp, program) + state.progLength + 1;
+ resize = offsetof(regexp_t, program) + state.progLength + 1;
re = heap_alloc(resize);
if (!re)
goto out;
if (re->classCount) {
re->classList = heap_alloc(re->classCount * sizeof(RECharSet));
if (!re->classList) {
- js_DestroyRegExp(re);
+ regexp_destroy(re);
re = NULL;
goto out;
}
}
endPC = EmitREBytecode(&state, re, state.treeDepth, re->program, state.result);
if (!endPC) {
- js_DestroyRegExp(re);
+ regexp_destroy(re);
re = NULL;
goto out;
}
* besides re exist here.
*/
if ((size_t)(endPC - re->program) != state.progLength + 1) {
- JSRegExp *tmp;
+ regexp_t *tmp;
assert((size_t)(endPC - re->program) < state.progLength + 1);
- resize = offsetof(JSRegExp, program) + (endPC - re->program);
+ resize = offsetof(regexp_t, program) + (endPC - re->program);
tmp = heap_realloc(re, resize);
if (tmp)
re = tmp;
re->flags = flags;
re->parenCount = state.parenCount;
re->source = str;
+ re->source_len = str_len;
out:
- jsheap_clear(mark);
+ heap_pool_clear(mark);
return re;
}
-
-static inline RegExpInstance *regexp_from_vdisp(vdisp_t *vdisp)
-{
- return (RegExpInstance*)vdisp->u.jsdisp;
-}
-
-static void set_last_index(RegExpInstance *This, DWORD last_index)
-{
- This->last_index = last_index;
- VariantClear(&This->last_index_var);
- num_set_val(&This->last_index_var, last_index);
-}
-
-static HRESULT do_regexp_match_next(script_ctx_t *ctx, RegExpInstance *regexp, DWORD rem_flags,
- const WCHAR *str, DWORD len, const WCHAR **cp, match_result_t **parens, DWORD *parens_size,
- DWORD *parens_cnt, match_result_t *ret)
-{
- REMatchState *x, *result;
- REGlobalData gData;
- DWORD matchlen;
-
- gData.cpbegin = *cp;
- gData.cpend = str + len;
- gData.start = *cp-str;
- gData.skipped = 0;
- gData.pool = &ctx->tmp_heap;
-
- x = InitMatch(NULL, &gData, regexp->jsregexp, gData.cpend - gData.cpbegin);
- if(!x) {
- WARN("InitMatch failed\n");
- return E_FAIL;
- }
-
- x->cp = *cp;
- result = MatchRegExp(&gData, x);
- if(!gData.ok) {
- WARN("MatchRegExp failed\n");
- return E_FAIL;
- }
-
- if(!result) {
- if(rem_flags & REM_RESET_INDEX)
- set_last_index(regexp, 0);
- return S_FALSE;
- }
-
- if(parens) {
- if(regexp->jsregexp->parenCount > *parens_size) {
- match_result_t *new_parens;
-
- if(*parens)
- new_parens = heap_realloc(*parens, sizeof(match_result_t)*regexp->jsregexp->parenCount);
- else
- new_parens = heap_alloc(sizeof(match_result_t)*regexp->jsregexp->parenCount);
- if(!new_parens)
- return E_OUTOFMEMORY;
-
- *parens = new_parens;
- }
- }
-
- /* FIXME: We often already have a copy of input string that we could use to store last match */
- if(!(rem_flags & REM_NO_CTX_UPDATE) &&
- (!ctx->last_match || len != SysStringLen(ctx->last_match) || strncmpW(ctx->last_match, str, len))) {
- BSTR last_match;
-
- last_match = SysAllocStringLen(str, len);
- if(!last_match)
- return E_OUTOFMEMORY;
- SysFreeString(ctx->last_match);
- ctx->last_match = last_match;
- }
-
- if(parens) {
- DWORD i;
-
- *parens_cnt = regexp->jsregexp->parenCount;
-
- for(i=0; i < regexp->jsregexp->parenCount; i++) {
- if(result->parens[i].index == -1) {
- (*parens)[i].str = NULL;
- (*parens)[i].len = 0;
- }else {
- (*parens)[i].str = *cp + result->parens[i].index;
- (*parens)[i].len = result->parens[i].length;
- }
- }
- }
-
- matchlen = (result->cp-*cp) - gData.skipped;
- *cp = result->cp;
- ret->str = result->cp-matchlen;
- ret->len = matchlen;
- set_last_index(regexp, result->cp-str);
-
- if(!(rem_flags & REM_NO_CTX_UPDATE)) {
- ctx->last_match_index = ret->str-str;
- ctx->last_match_length = matchlen;
- }
-
- return S_OK;
-}
-
-HRESULT regexp_match_next(script_ctx_t *ctx, DispatchEx *dispex, DWORD rem_flags, const WCHAR *str,
- DWORD len, const WCHAR **cp, match_result_t **parens, DWORD *parens_size, DWORD *parens_cnt,
- match_result_t *ret)
-{
- RegExpInstance *regexp = (RegExpInstance*)dispex;
- jsheap_t *mark;
- HRESULT hres;
-
- if((rem_flags & REM_CHECK_GLOBAL) && !(regexp->jsregexp->flags & JSREG_GLOB))
- return S_FALSE;
-
- mark = jsheap_mark(&ctx->tmp_heap);
-
- hres = do_regexp_match_next(ctx, regexp, rem_flags, str, len, cp, parens, parens_size, parens_cnt, ret);
-
- jsheap_clear(mark);
- return hres;
-}
-
-HRESULT regexp_match(script_ctx_t *ctx, DispatchEx *dispex, const WCHAR *str, DWORD len, BOOL gflag,
- match_result_t **match_result, DWORD *result_cnt)
-{
- RegExpInstance *This = (RegExpInstance*)dispex;
- match_result_t *ret = NULL, cres;
- const WCHAR *cp = str;
- DWORD i=0, ret_size = 0;
- jsheap_t *mark;
- HRESULT hres;
-
- mark = jsheap_mark(&ctx->tmp_heap);
-
- while(1) {
- hres = do_regexp_match_next(ctx, This, 0, str, len, &cp, NULL, NULL, NULL, &cres);
- if(hres == S_FALSE) {
- hres = S_OK;
- break;
- }
-
- if(FAILED(hres))
- break;
-
- if(ret_size == i) {
- if(ret)
- ret = heap_realloc(ret, (ret_size <<= 1) * sizeof(match_result_t));
- else
- ret = heap_alloc((ret_size=4) * sizeof(match_result_t));
- if(!ret) {
- hres = E_OUTOFMEMORY;
- break;
- }
- }
-
- ret[i++] = cres;
-
- if(!gflag && !(This->jsregexp->flags & JSREG_GLOB)) {
- hres = S_OK;
- break;
- }
- }
-
- jsheap_clear(mark);
- if(FAILED(hres)) {
- heap_free(ret);
- return hres;
- }
-
- *match_result = ret;
- *result_cnt = i;
- return S_OK;
-}
-
-static HRESULT RegExp_source(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
-{
- TRACE("\n");
-
- switch(flags) {
- case DISPATCH_PROPERTYGET: {
- RegExpInstance *This = regexp_from_vdisp(jsthis);
-
- V_VT(retv) = VT_BSTR;
- V_BSTR(retv) = SysAllocString(This->str);
- if(!V_BSTR(retv))
- return E_OUTOFMEMORY;
- break;
- }
- default:
- FIXME("Unimplemnted flags %x\n", flags);
- return E_NOTIMPL;
- }
-
- return S_OK;
-}
-
-static HRESULT RegExp_global(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
-{
- FIXME("\n");
- return E_NOTIMPL;
-}
-
-static HRESULT RegExp_ignoreCase(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
-{
- FIXME("\n");
- return E_NOTIMPL;
-}
-
-static HRESULT RegExp_multiline(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
-{
- FIXME("\n");
- return E_NOTIMPL;
-}
-
-static INT index_from_var(script_ctx_t *ctx, VARIANT *v)
-{
- jsexcept_t ei;
- VARIANT num;
- HRESULT hres;
-
- memset(&ei, 0, sizeof(ei));
- hres = to_number(ctx, v, &ei, &num);
- if(FAILED(hres)) { /* FIXME: Move ignoring exceptions to to_promitive */
- VariantClear(&ei.var);
- return 0;
- }
-
- if(V_VT(&num) == VT_R8) {
- DOUBLE d = floor(V_R8(&num));
- return (DOUBLE)(INT)d == d ? d : 0;
- }
-
- return V_I4(&num);
-}
-
-static HRESULT RegExp_lastIndex(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
-{
- TRACE("\n");
-
- switch(flags) {
- case DISPATCH_PROPERTYGET: {
- RegExpInstance *regexp = regexp_from_vdisp(jsthis);
-
- V_VT(retv) = VT_EMPTY;
- return VariantCopy(retv, ®exp->last_index_var);
- }
- case DISPATCH_PROPERTYPUT: {
- RegExpInstance *regexp = regexp_from_vdisp(jsthis);
- VARIANT *arg;
- HRESULT hres;
-
- arg = get_arg(dp,0);
- hres = VariantCopy(®exp->last_index_var, arg);
- if(FAILED(hres))
- return hres;
-
- regexp->last_index = index_from_var(ctx, arg);
- break;
- }
- default:
- FIXME("unimplemented flags: %x\n", flags);
- return E_NOTIMPL;
- }
-
- return S_OK;
-}
-
-static HRESULT RegExp_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
-{
- FIXME("\n");
- return E_NOTIMPL;
-}
-
-static HRESULT create_match_array(script_ctx_t *ctx, BSTR input, const match_result_t *result,
- const match_result_t *parens, DWORD parens_cnt, jsexcept_t *ei, IDispatch **ret)
-{
- DispatchEx *array;
- VARIANT var;
- int i;
- HRESULT hres = S_OK;
-
- static const WCHAR indexW[] = {'i','n','d','e','x',0};
- static const WCHAR inputW[] = {'i','n','p','u','t',0};
- static const WCHAR zeroW[] = {'0',0};
-
- hres = create_array(ctx, parens_cnt+1, &array);
- if(FAILED(hres))
- return hres;
-
- for(i=0; i < parens_cnt; i++) {
- V_VT(&var) = VT_BSTR;
- V_BSTR(&var) = SysAllocStringLen(parens[i].str, parens[i].len);
- if(!V_BSTR(&var)) {
- hres = E_OUTOFMEMORY;
- break;
- }
-
- hres = jsdisp_propput_idx(array, i+1, &var, ei, NULL/*FIXME*/);
- SysFreeString(V_BSTR(&var));
- if(FAILED(hres))
- break;
- }
-
- while(SUCCEEDED(hres)) {
- V_VT(&var) = VT_I4;
- V_I4(&var) = result->str-input;
- hres = jsdisp_propput_name(array, indexW, &var, ei, NULL/*FIXME*/);
- if(FAILED(hres))
- break;
-
- V_VT(&var) = VT_BSTR;
- V_BSTR(&var) = input;
- hres = jsdisp_propput_name(array, inputW, &var, ei, NULL/*FIXME*/);
- if(FAILED(hres))
- break;
-
- V_BSTR(&var) = SysAllocStringLen(result->str, result->len);
- if(!V_BSTR(&var)) {
- hres = E_OUTOFMEMORY;
- break;
- }
- hres = jsdisp_propput_name(array, zeroW, &var, ei, NULL/*FIXME*/);
- SysFreeString(V_BSTR(&var));
- break;
- }
-
- if(FAILED(hres)) {
- jsdisp_release(array);
- return hres;
- }
-
- *ret = (IDispatch*)_IDispatchEx_(array);
- return S_OK;
-}
-
-static HRESULT run_exec(script_ctx_t *ctx, vdisp_t *jsthis, VARIANT *arg, jsexcept_t *ei, BSTR *input,
- match_result_t *match, match_result_t **parens, DWORD *parens_cnt, VARIANT_BOOL *ret)
-{
- RegExpInstance *regexp;
- DWORD parens_size = 0, last_index = 0, length;
- const WCHAR *cp;
- BSTR string;
- HRESULT hres;
-
- if(!is_vclass(jsthis, JSCLASS_REGEXP)) {
- FIXME("Not a RegExp\n");
- return E_NOTIMPL;
- }
-
- regexp = regexp_from_vdisp(jsthis);
-
- if(arg) {
- hres = to_string(ctx, arg, ei, &string);
- if(FAILED(hres))
- return hres;
- length = SysStringLen(string);
- }else {
- string = NULL;
- length = 0;
- }
-
- if(regexp->jsregexp->flags & JSREG_GLOB) {
- if(regexp->last_index < 0) {
- SysFreeString(string);
- set_last_index(regexp, 0);
- *ret = VARIANT_FALSE;
- if(input) {
- *input = NULL;
- }
- return S_OK;
- }
-
- last_index = regexp->last_index;
- }
-
- cp = string + last_index;
- hres = regexp_match_next(ctx, ®exp->dispex, REM_RESET_INDEX, string, length, &cp, parens,
- parens ? &parens_size : NULL, parens_cnt, match);
- if(FAILED(hres)) {
- SysFreeString(string);
- return hres;
- }
-
- *ret = hres == S_OK ? VARIANT_TRUE : VARIANT_FALSE;
- if(input) {
- *input = string;
- }else {
- SysFreeString(string);
- }
- return S_OK;
-}
-
-static HRESULT RegExp_exec(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
-{
- match_result_t *parens = NULL, match;
- DWORD parens_cnt = 0;
- VARIANT_BOOL b;
- BSTR string;
- HRESULT hres;
-
- TRACE("\n");
-
- hres = run_exec(ctx, jsthis, arg_cnt(dp) ? get_arg(dp,0) : NULL, ei, &string, &match, &parens, &parens_cnt, &b);
- if(FAILED(hres))
- return hres;
-
- if(retv) {
- if(b) {
- IDispatch *ret;
-
- hres = create_match_array(ctx, string, &match, parens, parens_cnt, ei, &ret);
- if(SUCCEEDED(hres)) {
- V_VT(retv) = VT_DISPATCH;
- V_DISPATCH(retv) = ret;
- }
- }else {
- V_VT(retv) = VT_NULL;
- }
- }
-
- heap_free(parens);
- SysFreeString(string);
- return hres;
-}
-
-static HRESULT RegExp_test(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
-{
- match_result_t match;
- VARIANT undef_var;
- VARIANT_BOOL b;
- DWORD argc;
- HRESULT hres;
-
- TRACE("\n");
-
- argc = arg_cnt(dp);
- if(!argc) {
- V_VT(&undef_var) = VT_BSTR;
- V_BSTR(&undef_var) = SysAllocString(undefinedW);
- if(!V_BSTR(&undef_var))
- return E_OUTOFMEMORY;
- }
-
- hres = run_exec(ctx, jsthis, argc ? get_arg(dp,0) : &undef_var, ei, NULL, &match, NULL, NULL, &b);
- if(!argc)
- SysFreeString(V_BSTR(&undef_var));
- if(FAILED(hres))
- return hres;
-
- if(retv) {
- V_VT(retv) = VT_BOOL;
- V_BOOL(retv) = b;
- }
- return S_OK;
-}
-
-static HRESULT RegExp_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
-{
- TRACE("\n");
-
- switch(flags) {
- case INVOKE_FUNC:
- return throw_type_error(ctx, ei, IDS_NOT_FUNC, NULL);
- default:
- FIXME("unimplemented flags %x\n", flags);
- return E_NOTIMPL;
- }
-
- return S_OK;
-}
-
-static void RegExp_destructor(DispatchEx *dispex)
-{
- RegExpInstance *This = (RegExpInstance*)dispex;
-
- if(This->jsregexp)
- js_DestroyRegExp(This->jsregexp);
- VariantClear(&This->last_index_var);
- SysFreeString(This->str);
- heap_free(This);
-}
-
-static const builtin_prop_t RegExp_props[] = {
- {execW, RegExp_exec, PROPF_METHOD|1},
- {globalW, RegExp_global, 0},
- {ignoreCaseW, RegExp_ignoreCase, 0},
- {lastIndexW, RegExp_lastIndex, 0},
- {multilineW, RegExp_multiline, 0},
- {sourceW, RegExp_source, 0},
- {testW, RegExp_test, PROPF_METHOD|1},
- {toStringW, RegExp_toString, PROPF_METHOD}
-};
-
-static const builtin_info_t RegExp_info = {
- JSCLASS_REGEXP,
- {NULL, RegExp_value, 0},
- sizeof(RegExp_props)/sizeof(*RegExp_props),
- RegExp_props,
- RegExp_destructor,
- NULL
-};
-
-static HRESULT alloc_regexp(script_ctx_t *ctx, DispatchEx *object_prototype, RegExpInstance **ret)
-{
- RegExpInstance *regexp;
- HRESULT hres;
-
- regexp = heap_alloc_zero(sizeof(RegExpInstance));
- if(!regexp)
- return E_OUTOFMEMORY;
-
- if(object_prototype)
- hres = init_dispex(®exp->dispex, ctx, &RegExp_info, object_prototype);
- else
- hres = init_dispex_from_constr(®exp->dispex, ctx, &RegExp_info, ctx->regexp_constr);
-
- if(FAILED(hres)) {
- heap_free(regexp);
- return hres;
- }
-
- *ret = regexp;
- return S_OK;
-}
-
-HRESULT create_regexp(script_ctx_t *ctx, const WCHAR *exp, int len, DWORD flags, DispatchEx **ret)
-{
- RegExpInstance *regexp;
- HRESULT hres;
-
- TRACE("%s %x\n", debugstr_w(exp), flags);
-
- hres = alloc_regexp(ctx, NULL, ®exp);
- if(FAILED(hres))
- return hres;
-
- if(len == -1)
- regexp->str = SysAllocString(exp);
- else
- regexp->str = SysAllocStringLen(exp, len);
- if(!regexp->str) {
- jsdisp_release(®exp->dispex);
- return E_OUTOFMEMORY;
- }
-
- regexp->jsregexp = js_NewRegExp(ctx, regexp->str, flags, FALSE);
- if(!regexp->jsregexp) {
- WARN("js_NewRegExp failed\n");
- jsdisp_release(®exp->dispex);
- return E_FAIL;
- }
-
- V_VT(®exp->last_index_var) = VT_I4;
- V_I4(®exp->last_index_var) = 0;
-
- *ret = ®exp->dispex;
- return S_OK;
-}
-
-HRESULT create_regexp_var(script_ctx_t *ctx, VARIANT *src_arg, VARIANT *flags_arg, DispatchEx **ret)
-{
- const WCHAR *opt = emptyW, *src;
- DWORD flags;
- HRESULT hres;
-
- if(V_VT(src_arg) == VT_DISPATCH) {
- DispatchEx *obj;
-
- obj = iface_to_jsdisp((IUnknown*)V_DISPATCH(src_arg));
- if(obj) {
- if(is_class(obj, JSCLASS_REGEXP)) {
- RegExpInstance *regexp = (RegExpInstance*)obj;
-
- hres = create_regexp(ctx, regexp->str, -1, regexp->jsregexp->flags, ret);
- jsdisp_release(obj);
- return hres;
- }
-
- jsdisp_release(obj);
- }
- }
-
- if(V_VT(src_arg) != VT_BSTR) {
- FIXME("flags_arg = %s\n", debugstr_variant(flags_arg));
- return E_NOTIMPL;
- }
-
- src = V_BSTR(src_arg);
-
- if(flags_arg) {
- if(V_VT(flags_arg) != VT_BSTR) {
- FIXME("unimplemented for vt %d\n", V_VT(flags_arg));
- return E_NOTIMPL;
- }
-
- opt = V_BSTR(flags_arg);
- }
-
- hres = parse_regexp_flags(opt, strlenW(opt), &flags);
- if(FAILED(hres))
- return hres;
-
- return create_regexp(ctx, src, -1, flags, ret);
-}
-
-HRESULT regexp_string_match(script_ctx_t *ctx, DispatchEx *re, BSTR str,
- VARIANT *retv, jsexcept_t *ei)
-{
- RegExpInstance *regexp = (RegExpInstance*)re;
- match_result_t *match_result;
- DWORD match_cnt, i, length;
- DispatchEx *array;
- VARIANT var;
- HRESULT hres;
-
- length = SysStringLen(str);
-
- if(!(regexp->jsregexp->flags & JSREG_GLOB)) {
- match_result_t match, *parens = NULL;
- DWORD parens_cnt, parens_size = 0;
- const WCHAR *cp = str;
-
- hres = regexp_match_next(ctx, ®exp->dispex, 0, str, length, &cp, &parens, &parens_size, &parens_cnt, &match);
- if(FAILED(hres))
- return hres;
-
- if(retv) {
- if(hres == S_OK) {
- IDispatch *ret;
-
- hres = create_match_array(ctx, str, &match, parens, parens_cnt, ei, &ret);
- if(SUCCEEDED(hres)) {
- V_VT(retv) = VT_DISPATCH;
- V_DISPATCH(retv) = ret;
- }
- }else {
- V_VT(retv) = VT_NULL;
- }
- }
-
- heap_free(parens);
- return S_OK;
- }
-
- hres = regexp_match(ctx, ®exp->dispex, str, length, FALSE, &match_result, &match_cnt);
- if(FAILED(hres))
- return hres;
-
- if(!match_cnt) {
- TRACE("no match\n");
-
- if(retv)
- V_VT(retv) = VT_NULL;
- return S_OK;
- }
-
- hres = create_array(ctx, match_cnt, &array);
- if(FAILED(hres))
- return hres;
-
- V_VT(&var) = VT_BSTR;
-
- for(i=0; i < match_cnt; i++) {
- V_BSTR(&var) = SysAllocStringLen(match_result[i].str, match_result[i].len);
- if(!V_BSTR(&var)) {
- hres = E_OUTOFMEMORY;
- break;
- }
-
- hres = jsdisp_propput_idx(array, i, &var, ei, NULL/*FIXME*/);
- SysFreeString(V_BSTR(&var));
- if(FAILED(hres))
- break;
- }
-
- heap_free(match_result);
-
- if(SUCCEEDED(hres) && retv) {
- V_VT(retv) = VT_DISPATCH;
- V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(array);
- }else {
- jsdisp_release(array);
- }
- return hres;
-}
-
-static HRESULT RegExpConstr_leftContext(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
- DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
-{
- TRACE("\n");
-
- switch(flags) {
- case DISPATCH_PROPERTYGET: {
- BSTR ret;
-
- ret = SysAllocStringLen(ctx->last_match, ctx->last_match_index);
- if(!ret)
- return E_OUTOFMEMORY;
-
- V_VT(retv) = VT_BSTR;
- V_BSTR(retv) = ret;
- }
- case DISPATCH_PROPERTYPUT:
- return S_OK;
- default:
- FIXME("unsupported flags\n");
- return E_NOTIMPL;
- }
-
- return S_OK;
-}
-
-static HRESULT RegExpConstr_rightContext(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
- DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
-{
- TRACE("\n");
-
- switch(flags) {
- case DISPATCH_PROPERTYGET: {
- BSTR ret;
-
- ret = SysAllocString(ctx->last_match+ctx->last_match_index+ctx->last_match_length);
- if(!ret)
- return E_OUTOFMEMORY;
-
- V_VT(retv) = VT_BSTR;
- V_BSTR(retv) = ret;
- }
- case DISPATCH_PROPERTYPUT:
- return S_OK;
- default:
- FIXME("unsupported flags\n");
- return E_NOTIMPL;
- }
-
- return S_OK;
-}
-
-static HRESULT RegExpConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
-{
- TRACE("\n");
-
- switch(flags) {
- case DISPATCH_METHOD:
- if(arg_cnt(dp)) {
- VARIANT *arg = get_arg(dp,0);
- if(V_VT(arg) == VT_DISPATCH) {
- DispatchEx *jsdisp = iface_to_jsdisp((IUnknown*)V_DISPATCH(arg));
- if(jsdisp) {
- if(is_class(jsdisp, JSCLASS_REGEXP)) {
- if(arg_cnt(dp) > 1 && V_VT(get_arg(dp,1)) != VT_EMPTY) {
- jsdisp_release(jsdisp);
- return throw_regexp_error(ctx, ei, IDS_REGEXP_SYNTAX_ERROR, NULL);
- }
-
- if(retv) {
- V_VT(retv) = VT_DISPATCH;
- V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(jsdisp);
- }else {
- jsdisp_release(jsdisp);
- }
- return S_OK;
- }
- jsdisp_release(jsdisp);
- }
- }
- }
- /* fall through */
- case DISPATCH_CONSTRUCT: {
- DispatchEx *ret;
- HRESULT hres;
-
- if(!arg_cnt(dp)) {
- FIXME("no args\n");
- return E_NOTIMPL;
- }
-
- hres = create_regexp_var(ctx, get_arg(dp,0), arg_cnt(dp) > 1 ? get_arg(dp,1) : NULL, &ret);
- if(FAILED(hres))
- return hres;
-
- if(retv) {
- V_VT(retv) = VT_DISPATCH;
- V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(ret);
- }else {
- jsdisp_release(ret);
- }
- return S_OK;
- }
- default:
- FIXME("unimplemented flags: %x\n", flags);
- return E_NOTIMPL;
- }
-
- return S_OK;
-}
-
-static const builtin_prop_t RegExpConstr_props[] = {
- {leftContextW, RegExpConstr_leftContext, 0},
- {rightContextW, RegExpConstr_rightContext, 0}
-};
-
-static const builtin_info_t RegExpConstr_info = {
- JSCLASS_FUNCTION,
- {NULL, Function_value, 0},
- sizeof(RegExpConstr_props)/sizeof(*RegExpConstr_props),
- RegExpConstr_props,
- NULL,
- NULL
-};
-
-HRESULT create_regexp_constr(script_ctx_t *ctx, DispatchEx *object_prototype, DispatchEx **ret)
-{
- RegExpInstance *regexp;
- HRESULT hres;
-
- static const WCHAR RegExpW[] = {'R','e','g','E','x','p',0};
-
- hres = alloc_regexp(ctx, object_prototype, ®exp);
- if(FAILED(hres))
- return hres;
-
- hres = create_builtin_function(ctx, RegExpConstr_value, RegExpW, &RegExpConstr_info,
- PROPF_CONSTR|2, ®exp->dispex, ret);
-
- jsdisp_release(®exp->dispex);
- return hres;
-}
-
-HRESULT parse_regexp_flags(const WCHAR *str, DWORD str_len, DWORD *ret)
-{
- const WCHAR *p;
- DWORD flags = 0;
-
- for (p = str; p < str+str_len; p++) {
- switch (*p) {
- case 'g':
- flags |= JSREG_GLOB;
- break;
- case 'i':
- flags |= JSREG_FOLD;
- break;
- case 'm':
- flags |= JSREG_MULTILINE;
- break;
- case 'y':
- flags |= JSREG_STICKY;
- break;
- default:
- WARN("wrong flag %c\n", *p);
- return E_FAIL;
- }
- }
-
- *ret = flags;
- return S_OK;
-}
--- /dev/null
+/*
+ * Copyright 2008 Jacek Caban for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+/*
+ * Code in this file is based on files:
+ * js/src/jsregexp.h
+ * js/src/jsregexp.c
+ * from Mozilla project, released under LGPL 2.1 or later.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ */
+
+#define REG_FOLD 0x01 /* fold uppercase to lowercase */
+#define REG_GLOB 0x02 /* global exec, creates array of matches */
+#define REG_MULTILINE 0x04 /* treat ^ and $ as begin and end of line */
+#define REG_STICKY 0x08 /* only match starting at lastIndex */
+
+typedef struct RECapture {
+ ptrdiff_t index; /* start of contents, -1 for empty */
+ size_t length; /* length of capture */
+} RECapture;
+
+typedef struct match_state_t {
+ const WCHAR *cp;
+ DWORD match_len;
+
+ DWORD paren_count;
+ RECapture parens[1];
+} match_state_t;
+
+typedef BYTE jsbytecode;
+
+typedef struct regexp_t {
+ WORD flags; /* flags, see jsapi.h's REG_* defines */
+ size_t parenCount; /* number of parenthesized submatches */
+ size_t classCount; /* count [...] bitmaps */
+ struct RECharSet *classList; /* list of [...] bitmaps */
+ const WCHAR *source; /* locked source string, sans // */
+ DWORD source_len;
+ jsbytecode program[1]; /* regular expression bytecode */
+} regexp_t;
+
+regexp_t* regexp_new(void*, heap_pool_t*, const WCHAR*, DWORD, WORD, BOOL) DECLSPEC_HIDDEN;
+void regexp_destroy(regexp_t*) DECLSPEC_HIDDEN;
+HRESULT regexp_execute(regexp_t*, void*, heap_pool_t*, const WCHAR*,
+ DWORD, match_state_t*) DECLSPEC_HIDDEN;
+
+static inline match_state_t* alloc_match_state(regexp_t *regexp,
+ heap_pool_t *pool, const WCHAR *pos)
+{
+ size_t size = offsetof(match_state_t, parens) + regexp->parenCount*sizeof(RECapture);
+ match_state_t *ret;
+
+ ret = pool ? heap_pool_alloc(pool, size) : heap_alloc(size);
+ if(!ret)
+ return NULL;
+
+ ret->cp = pos;
+ return ret;
+}
#include <windef.h>
+#define JSCRIPT_MAJOR_VERSION 5
+#define JSCRIPT_MINOR_VERSION 8
+#define JSCRIPT_BUILD_VERSION 16475
+
#define IDS_TO_PRIMITIVE 0x0001
#define IDS_INVALID_CALL_ARG 0x0005
+#define IDS_SUBSCRIPT_OUT_OF_RANGE 0x0009
+#define IDS_OBJECT_REQUIRED 0x01A8
#define IDS_CREATE_OBJ_ERROR 0x01AD
#define IDS_NO_PROPERTY 0x01B6
+#define IDS_UNSUPPORTED_ACTION 0x01BD
#define IDS_ARG_NOT_OPT 0x01c1
#define IDS_SYNTAX_ERROR 0x03EA
#define IDS_SEMICOLON 0x03EC
#define IDS_LBRACKET 0x03ED
#define IDS_RBRACKET 0x03EE
+#define IDS_INVALID_CHAR 0x03F6
#define IDS_UNTERMINATED_STR 0x03F7
+#define IDS_MISPLACED_RETURN 0x03FA
+#define IDS_INVALID_BREAK 0x03FB
+#define IDS_INVALID_CONTINUE 0x03FC
+#define IDS_LABEL_REDEFINED 0x0401
+#define IDS_LABEL_NOT_FOUND 0x0402
+#define IDS_DISABLED_CC 0x0406
#define IDS_NOT_FUNC 0x138A
#define IDS_NOT_DATE 0x138E
#define IDS_NOT_NUM 0x1389
#define IDS_ILLEGAL_ASSIGN 0x1390
#define IDS_UNDEFINED 0x1391
#define IDS_NOT_BOOL 0x1392
+#define IDS_INVALID_DELETE 0x1394
+#define IDS_NOT_VBARRAY 0x1395
#define IDS_JSCRIPT_EXPECTED 0x1396
#define IDS_REGEXP_SYNTAX_ERROR 0x1399
#define IDS_URI_INVALID_CHAR 0x13A0
+#define IDS_URI_INVALID_CODING 0x13A1
+#define IDS_FRACTION_DIGITS_OUT_OF_RANGE 0x13A2
+#define IDS_PRECISION_OUT_OF_RANGE 0x13A3
#define IDS_INVALID_LENGTH 0x13A5
#define IDS_ARRAY_EXPECTED 0x13A7
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
-/* @makedep: jscript.inf */
-REGINST REGINST jscript.inf
+/* @makedep: jscript.rgs */
+2 WINE_REGISTRY jscript.rgs
+
+3 WINE_REGISTRY jscript_classes.rgs
/* @makedep: jsglobal.tlb */
1 TYPELIB jsglobal.tlb
+#define WINE_FILEDESCRIPTION_STR "Wine JScript"
+#define WINE_FILENAME_STR "jscript.dll"
+#define WINE_FILEVERSION 5,7,7601,16982
+#define WINE_FILEVERSION_STR "5.8.7601.16982"
+#define WINE_PRODUCTVERSION 5,8,7601,16982
+#define WINE_PRODUCTVERSION_STR "5.8.7601.16982"
+
+#include "wine/wine_common_ver.rc"
+
#ifdef LANGUAGE_EN_US
#include "jscript_En.rc"
#endif
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
+#include "config.h"
+#include "wine/port.h"
+
#include "jscript.h"
+#include "regexp.h"
#include <wine/debug.h>
WINE_DEFAULT_DEBUG_CHANNEL(jscript);
-typedef struct {
- DispatchEx dispex;
+#define UINT32_MAX 0xffffffff
- WCHAR *str;
- DWORD length;
+typedef struct {
+ jsdisp_t dispex;
+ jsstr_t *str;
} StringInstance;
static const WCHAR lengthW[] = {'l','e','n','g','t','h',0};
return is_vclass(jsthis, JSCLASS_STRING) ? string_from_vdisp(jsthis) : NULL;
}
-static HRESULT get_string_val(script_ctx_t *ctx, vdisp_t *jsthis, jsexcept_t *ei,
- const WCHAR **str, DWORD *len, BSTR *val_str)
+static HRESULT get_string_val(script_ctx_t *ctx, vdisp_t *jsthis, jsstr_t **val)
{
StringInstance *string;
- VARIANT this_var;
- HRESULT hres;
if((string = string_this(jsthis))) {
- *str = string->str;
- *len = string->length;
- *val_str = NULL;
+ *val = jsstr_addref(string->str);
return S_OK;
}
- V_VT(&this_var) = VT_DISPATCH;
- V_DISPATCH(&this_var) = jsthis->u.disp;
- hres = to_string(ctx, &this_var, ei, val_str);
- if(FAILED(hres))
- return hres;
-
- *str = *val_str;
- *len = SysStringLen(*val_str);
- return S_OK;
+ return to_string(ctx, jsval_disp(jsthis->u.disp), val);
}
-static HRESULT String_length(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT String_length(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
TRACE("%p\n", jsthis);
case DISPATCH_PROPERTYGET: {
StringInstance *string = string_from_vdisp(jsthis);
- V_VT(retv) = VT_I4;
- V_I4(retv) = string->length;
+ *r = jsval_number(jsstr_length(string->str));
break;
}
default:
return S_OK;
}
-static HRESULT stringobj_to_string(vdisp_t *jsthis, VARIANT *retv)
+static HRESULT stringobj_to_string(vdisp_t *jsthis, jsval_t *r)
{
StringInstance *string;
return E_FAIL;
}
- if(retv) {
- BSTR str = SysAllocString(string->str);
- if(!str)
- return E_OUTOFMEMORY;
-
- V_VT(retv) = VT_BSTR;
- V_BSTR(retv) = str;
- }
+ if(r)
+ *r = jsval_string(jsstr_addref(string->str));
return S_OK;
}
/* ECMA-262 3rd Edition 15.5.4.2 */
-static HRESULT String_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT String_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
TRACE("\n");
- return stringobj_to_string(jsthis, retv);
+ return stringobj_to_string(jsthis, r);
}
/* ECMA-262 3rd Edition 15.5.4.2 */
-static HRESULT String_valueOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT String_valueOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
TRACE("\n");
- return stringobj_to_string(jsthis, retv);
+ return stringobj_to_string(jsthis, r);
}
-static HRESULT do_attributeless_tag_format(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp, const WCHAR *tagname)
+static HRESULT do_attributeless_tag_format(script_ctx_t *ctx, vdisp_t *jsthis, jsval_t *r, const WCHAR *tagname)
{
- const WCHAR *str;
- DWORD length;
- BSTR val_str = NULL;
+ unsigned tagname_len;
+ jsstr_t *str, *ret;
+ WCHAR *ptr;
HRESULT hres;
- static const WCHAR tagfmt[] = {'<','%','s','>','%','s','<','/','%','s','>',0};
-
- hres = get_string_val(ctx, jsthis, ei, &str, &length, &val_str);
+ hres = get_string_val(ctx, jsthis, &str);
if(FAILED(hres))
return hres;
- if(retv) {
- BSTR ret = SysAllocStringLen(NULL, length + 2*strlenW(tagname) + 5);
- if(!ret) {
- SysFreeString(val_str);
- return E_OUTOFMEMORY;
- }
+ if(!r) {
+ jsstr_release(str);
+ return S_OK;
+ }
- sprintfW(ret, tagfmt, tagname, str, tagname);
+ tagname_len = strlenW(tagname);
- V_VT(retv) = VT_BSTR;
- V_BSTR(retv) = ret;
+ ret = jsstr_alloc_buf(jsstr_length(str) + 2*tagname_len + 5);
+ if(!ret) {
+ jsstr_release(str);
+ return E_OUTOFMEMORY;
}
- SysFreeString(val_str);
+ ptr = ret->str;
+ *ptr++ = '<';
+ memcpy(ptr, tagname, tagname_len*sizeof(WCHAR));
+ ptr += tagname_len;
+ *ptr++ = '>';
+
+ ptr += jsstr_flush(str, ptr);
+ jsstr_release(str);
+
+ *ptr++ = '<';
+ *ptr++ = '/';
+ memcpy(ptr, tagname, tagname_len*sizeof(WCHAR));
+ ptr += tagname_len;
+ *ptr = '>';
+
+ *r = jsval_string(ret);
return S_OK;
}
-static HRESULT do_attribute_tag_format(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
- DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp,
- const WCHAR *tagname, const WCHAR *attr)
+static HRESULT do_attribute_tag_format(script_ctx_t *ctx, vdisp_t *jsthis, unsigned argc, jsval_t *argv, jsval_t *r,
+ const WCHAR *tagname, const WCHAR *attrname)
{
- static const WCHAR tagfmtW[]
- = {'<','%','s',' ','%','s','=','\"','%','s','\"','>','%','s','<','/','%','s','>',0};
- static const WCHAR undefinedW[] = {'u','n','d','e','f','i','n','e','d',0};
-
- StringInstance *string;
- const WCHAR *str;
- DWORD length;
- BSTR attr_value, val_str = NULL;
+ jsstr_t *str, *attr_value = NULL;
HRESULT hres;
- if(!(string = string_this(jsthis))) {
- VARIANT this;
-
- V_VT(&this) = VT_DISPATCH;
- V_DISPATCH(&this) = jsthis->u.disp;
-
- hres = to_string(ctx, &this, ei, &val_str);
- if(FAILED(hres))
- return hres;
-
- str = val_str;
- length = SysStringLen(val_str);
- }
- else {
- str = string->str;
- length = string->length;
- }
+ hres = get_string_val(ctx, jsthis, &str);
+ if(FAILED(hres))
+ return hres;
- if(arg_cnt(dp)) {
- hres = to_string(ctx, get_arg(dp, 0), ei, &attr_value);
+ if(argc) {
+ hres = to_string(ctx, argv[0], &attr_value);
if(FAILED(hres)) {
- SysFreeString(val_str);
+ jsstr_release(str);
return hres;
}
- }
- else {
- attr_value = SysAllocString(undefinedW);
- if(!attr_value) {
- SysFreeString(val_str);
- return E_OUTOFMEMORY;
- }
- }
-
- if(retv) {
- BSTR ret = SysAllocStringLen(NULL, length + 2*strlenW(tagname)
- + strlenW(attr) + SysStringLen(attr_value) + 9);
- if(!ret) {
- SysFreeString(attr_value);
- SysFreeString(val_str);
- return E_OUTOFMEMORY;
+ }else {
+ attr_value = jsstr_undefined();
+ }
+
+ if(r) {
+ unsigned attrname_len = strlenW(attrname);
+ unsigned tagname_len = strlenW(tagname);
+ jsstr_t *ret;
+
+ ret = jsstr_alloc_buf(2*tagname_len + attrname_len + jsstr_length(attr_value) + jsstr_length(str) + 9);
+ if(ret) {
+ WCHAR *ptr = ret->str;
+
+ *ptr++ = '<';
+ memcpy(ptr, tagname, tagname_len*sizeof(WCHAR));
+ ptr += tagname_len;
+ *ptr++ = ' ';
+ memcpy(ptr, attrname, attrname_len*sizeof(WCHAR));
+ ptr += attrname_len;
+ *ptr++ = '=';
+ *ptr++ = '"';
+ ptr += jsstr_flush(attr_value, ptr);
+ *ptr++ = '"';
+ *ptr++ = '>';
+ ptr += jsstr_flush(str, ptr);
+
+ *ptr++ = '<';
+ *ptr++ = '/';
+ memcpy(ptr, tagname, tagname_len*sizeof(WCHAR));
+ ptr += tagname_len;
+ *ptr = '>';
+
+ *r = jsval_string(ret);
+ }else {
+ hres = E_OUTOFMEMORY;
}
-
- sprintfW(ret, tagfmtW, tagname, attr, attr_value, str, tagname);
-
- V_VT(retv) = VT_BSTR;
- V_BSTR(retv) = ret;
}
- SysFreeString(attr_value);
- SysFreeString(val_str);
- return S_OK;
+ jsstr_release(attr_value);
+ jsstr_release(str);
+ return hres;
}
-static HRESULT String_anchor(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT String_anchor(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
static const WCHAR fontW[] = {'A',0};
static const WCHAR colorW[] = {'N','A','M','E',0};
- return do_attribute_tag_format(ctx, jsthis, flags, dp, retv, ei, sp, fontW, colorW);
+ return do_attribute_tag_format(ctx, jsthis, argc, argv, r, fontW, colorW);
}
-static HRESULT String_big(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT String_big(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
static const WCHAR bigtagW[] = {'B','I','G',0};
- return do_attributeless_tag_format(ctx, jsthis, flags, dp, retv, ei, sp, bigtagW);
+ return do_attributeless_tag_format(ctx, jsthis, r, bigtagW);
}
-static HRESULT String_blink(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT String_blink(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
static const WCHAR blinktagW[] = {'B','L','I','N','K',0};
- return do_attributeless_tag_format(ctx, jsthis, flags, dp, retv, ei, sp, blinktagW);
+ return do_attributeless_tag_format(ctx, jsthis, r, blinktagW);
}
-static HRESULT String_bold(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT String_bold(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
static const WCHAR boldtagW[] = {'B',0};
- return do_attributeless_tag_format(ctx, jsthis, flags, dp, retv, ei, sp, boldtagW);
+ return do_attributeless_tag_format(ctx, jsthis, r, boldtagW);
}
/* ECMA-262 3rd Edition 15.5.4.5 */
-static HRESULT String_charAt(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT String_charAt(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- const WCHAR *str;
- DWORD length;
- BSTR ret, val_str;
+ jsstr_t *str, *ret;
INT pos = 0;
HRESULT hres;
TRACE("\n");
- hres = get_string_val(ctx, jsthis, ei, &str, &length, &val_str);
+ hres = get_string_val(ctx, jsthis, &str);
if(FAILED(hres))
return hres;
- if(arg_cnt(dp)) {
- VARIANT num;
+ if(argc) {
+ double d;
- hres = to_integer(ctx, get_arg(dp, 0), ei, &num);
+ hres = to_integer(ctx, argv[0], &d);
if(FAILED(hres)) {
- SysFreeString(val_str);
+ jsstr_release(str);
return hres;
}
-
- if(V_VT(&num) == VT_I4) {
- pos = V_I4(&num);
- }else {
- WARN("pos = %lf\n", V_R8(&num));
- pos = -1;
- }
+ pos = is_int32(d) ? d : -1;
}
- if(!retv) {
- SysFreeString(val_str);
+ if(!r) {
+ jsstr_release(str);
return S_OK;
}
- if(0 <= pos && pos < length)
- ret = SysAllocStringLen(str+pos, 1);
- else
- ret = SysAllocStringLen(NULL, 0);
- SysFreeString(val_str);
- if(!ret) {
- return E_OUTOFMEMORY;
+ if(0 <= pos && pos < jsstr_length(str)) {
+ ret = jsstr_substr(str, pos, 1);
+ if(!ret)
+ return E_OUTOFMEMORY;
+ }else {
+ ret = jsstr_empty();
}
- V_VT(retv) = VT_BSTR;
- V_BSTR(retv) = ret;
+ *r = jsval_string(ret);
return S_OK;
}
/* ECMA-262 3rd Edition 15.5.4.5 */
-static HRESULT String_charCodeAt(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT String_charCodeAt(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- const WCHAR *str;
- BSTR val_str;
- DWORD length, idx = 0;
+ jsstr_t *str;
+ DWORD idx = 0;
HRESULT hres;
TRACE("\n");
- hres = get_string_val(ctx, jsthis, ei, &str, &length, &val_str);
+ hres = get_string_val(ctx, jsthis, &str);
if(FAILED(hres))
return hres;
- if(arg_cnt(dp) > 0) {
- VARIANT v;
+ if(argc > 0) {
+ double d;
- hres = to_integer(ctx, get_arg(dp, 0), ei, &v);
+ hres = to_integer(ctx, argv[0], &d);
if(FAILED(hres)) {
- SysFreeString(val_str);
+ jsstr_release(str);
return hres;
}
- if(V_VT(&v) != VT_I4 || V_I4(&v) < 0 || V_I4(&v) >= length) {
- if(retv) num_set_nan(&v);
- SysFreeString(val_str);
+ if(!is_int32(d) || d < 0 || d >= jsstr_length(str)) {
+ jsstr_release(str);
+ if(r)
+ *r = jsval_number(NAN);
return S_OK;
}
- idx = V_I4(&v);
+ idx = d;
}
- if(retv) {
- V_VT(retv) = VT_I4;
- V_I4(retv) = str[idx];
- }
+ if(r)
+ *r = jsval_number(str->str[idx]);
- SysFreeString(val_str);
+ jsstr_release(str);
return S_OK;
}
/* ECMA-262 3rd Edition 15.5.4.6 */
-static HRESULT String_concat(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT String_concat(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- BSTR *strs = NULL, ret = NULL;
- DWORD len = 0, i, l, str_cnt;
- VARIANT var;
+ unsigned len = 0, i, str_cnt;
+ jsstr_t **strs, *ret = NULL;
WCHAR *ptr;
HRESULT hres;
TRACE("\n");
- str_cnt = arg_cnt(dp)+1;
- strs = heap_alloc_zero(str_cnt * sizeof(BSTR));
+ str_cnt = argc+1;
+ strs = heap_alloc_zero(str_cnt * sizeof(*strs));
if(!strs)
return E_OUTOFMEMORY;
- V_VT(&var) = VT_DISPATCH;
- V_DISPATCH(&var) = jsthis->u.disp;
-
- hres = to_string(ctx, &var, ei, strs);
+ hres = to_string(ctx, jsval_disp(jsthis->u.disp), strs);
if(SUCCEEDED(hres)) {
- for(i=0; i < arg_cnt(dp); i++) {
- hres = to_string(ctx, get_arg(dp, i), ei, strs+i+1);
+ 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 += SysStringLen(strs[i]);
-
- ptr = ret = SysAllocStringLen(NULL, len);
-
for(i=0; i < str_cnt; i++) {
- l = SysStringLen(strs[i]);
- memcpy(ptr, strs[i], l*sizeof(WCHAR));
- ptr += l;
+ len += jsstr_length(strs[i]);
+ if(len > JSSTR_MAX_LENGTH) {
+ hres = E_OUTOFMEMORY;
+ break;
+ }
+ }
+
+ ret = jsstr_alloc_buf(len);
+ if(ret) {
+ ptr = ret->str;
+ for(i=0; i < str_cnt; i++)
+ ptr += jsstr_flush(strs[i], ptr);
+ }else {
+ hres = E_OUTOFMEMORY;
}
}
for(i=0; i < str_cnt; i++)
- SysFreeString(strs[i]);
+ jsstr_release(strs[i]);
heap_free(strs);
if(FAILED(hres))
return hres;
- if(retv) {
- V_VT(retv) = VT_BSTR;
- V_BSTR(retv) = ret;
- }else {
- SysFreeString(ret);
- }
+ if(r)
+ *r = jsval_string(ret);
+ else
+ jsstr_release(ret);
return S_OK;
}
-static HRESULT String_fixed(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT String_fixed(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
static const WCHAR fixedtagW[] = {'T','T',0};
- return do_attributeless_tag_format(ctx, jsthis, flags, dp, retv, ei, sp, fixedtagW);
+ return do_attributeless_tag_format(ctx, jsthis, r, fixedtagW);
}
-static HRESULT String_fontcolor(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT String_fontcolor(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
static const WCHAR fontW[] = {'F','O','N','T',0};
static const WCHAR colorW[] = {'C','O','L','O','R',0};
- return do_attribute_tag_format(ctx, jsthis, flags, dp, retv, ei, sp, fontW, colorW);
+ return do_attribute_tag_format(ctx, jsthis, argc, argv, r, fontW, colorW);
}
-static HRESULT String_fontsize(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT String_fontsize(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
static const WCHAR fontW[] = {'F','O','N','T',0};
static const WCHAR colorW[] = {'S','I','Z','E',0};
- return do_attribute_tag_format(ctx, jsthis, flags, dp, retv, ei, sp, fontW, colorW);
+ return do_attribute_tag_format(ctx, jsthis, argc, argv, r, fontW, colorW);
}
-static HRESULT String_indexOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT String_indexOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- DWORD length, pos = 0;
- const WCHAR *str;
- BSTR search_str, val_str;
+ jsstr_t *search_str, *str;
+ int length, pos = 0;
INT ret = -1;
HRESULT hres;
TRACE("\n");
- hres = get_string_val(ctx, jsthis, ei, &str, &length, &val_str);
+ hres = get_string_val(ctx, jsthis, &str);
if(FAILED(hres))
return hres;
- if(!arg_cnt(dp)) {
- if(retv) {
- V_VT(retv) = VT_I4;
- V_I4(retv) = -1;
- }
- SysFreeString(val_str);
+ length = jsstr_length(str);
+ if(!argc) {
+ if(r)
+ *r = jsval_number(-1);
+ jsstr_release(str);
return S_OK;
}
- hres = to_string(ctx, get_arg(dp,0), ei, &search_str);
+ hres = to_string(ctx, argv[0], &search_str);
if(FAILED(hres)) {
- SysFreeString(val_str);
+ jsstr_release(str);
return hres;
}
- if(arg_cnt(dp) >= 2) {
- VARIANT ival;
+ if(argc >= 2) {
+ double d;
- hres = to_integer(ctx, get_arg(dp,1), ei, &ival);
- if(SUCCEEDED(hres)) {
- if(V_VT(&ival) == VT_I4)
- pos = V_VT(&ival) > 0 ? V_I4(&ival) : 0;
- else
- pos = V_R8(&ival) > 0.0 ? length : 0;
- if(pos > length)
- pos = length;
- }
+ hres = to_integer(ctx, argv[1], &d);
+ if(SUCCEEDED(hres) && d > 0.0)
+ pos = is_int32(d) ? min(length, d) : length;
}
if(SUCCEEDED(hres)) {
const WCHAR *ptr;
- ptr = strstrW(str+pos, search_str);
+ ptr = strstrW(str->str+pos, search_str->str);
if(ptr)
- ret = ptr - str;
+ ret = ptr - str->str;
else
ret = -1;
}
- SysFreeString(search_str);
- SysFreeString(val_str);
+ jsstr_release(search_str);
+ jsstr_release(str);
if(FAILED(hres))
return hres;
- if(retv) {
- V_VT(retv) = VT_I4;
- V_I4(retv) = ret;
- }
+ if(r)
+ *r = jsval_number(ret);
return S_OK;
}
-static HRESULT String_italics(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT String_italics(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
static const WCHAR italicstagW[] = {'I',0};
- return do_attributeless_tag_format(ctx, jsthis, flags, dp, retv, ei, sp, italicstagW);
+ return do_attributeless_tag_format(ctx, jsthis, r, italicstagW);
}
/* ECMA-262 3rd Edition 15.5.4.8 */
-static HRESULT String_lastIndexOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT String_lastIndexOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- BSTR search_str, val_str;
- DWORD length, pos, search_len;
- const WCHAR *str;
+ unsigned pos = 0, search_len, length;
+ jsstr_t *search_str, *str;
INT ret = -1;
HRESULT hres;
TRACE("\n");
- hres = get_string_val(ctx, jsthis, ei, &str, &length, &val_str);
+ hres = get_string_val(ctx, jsthis, &str);
if(FAILED(hres))
return hres;
- if(!arg_cnt(dp)) {
- if(retv) {
- V_VT(retv) = VT_I4;
- V_I4(retv) = -1;
- }
- SysFreeString(val_str);
+ if(!argc) {
+ if(r)
+ *r = jsval_number(-1);
+ jsstr_release(str);
return S_OK;
}
- hres = to_string(ctx, get_arg(dp,0), ei, &search_str);
+ hres = to_string(ctx, argv[0], &search_str);
if(FAILED(hres)) {
- SysFreeString(val_str);
+ jsstr_release(str);
return hres;
}
- search_len = SysStringLen(search_str);
+ search_len = jsstr_length(search_str);
+ length = jsstr_length(str);
- if(arg_cnt(dp) >= 2) {
- VARIANT ival;
+ if(argc >= 2) {
+ double d;
- hres = to_integer(ctx, get_arg(dp,1), ei, &ival);
- if(SUCCEEDED(hres)) {
- if(V_VT(&ival) == VT_I4)
- pos = V_VT(&ival) > 0 ? V_I4(&ival) : 0;
- else
- pos = V_R8(&ival) > 0.0 ? length : 0;
- if(pos > length)
- pos = length;
- }
+ hres = to_integer(ctx, argv[1], &d);
+ if(SUCCEEDED(hres) && d > 0)
+ pos = is_int32(d) ? min(length, d) : length;
}else {
pos = length;
}
if(SUCCEEDED(hres) && length >= search_len) {
const WCHAR *ptr;
- for(ptr = str+min(pos, length-search_len); ptr >= str; ptr--) {
- if(!memcmp(ptr, search_str, search_len*sizeof(WCHAR))) {
- ret = ptr-str;
+ for(ptr = str->str+min(pos, length-search_len); ptr >= str->str; ptr--) {
+ if(!memcmp(ptr, search_str->str, search_len*sizeof(WCHAR))) {
+ ret = ptr-str->str;
break;
}
}
}
- SysFreeString(search_str);
- SysFreeString(val_str);
+ jsstr_release(search_str);
+ jsstr_release(str);
if(FAILED(hres))
return hres;
- if(retv) {
- V_VT(retv) = VT_I4;
- V_I4(retv) = ret;
- }
+ if(r)
+ *r = jsval_number(ret);
return S_OK;
}
-static HRESULT String_link(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT String_link(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
static const WCHAR fontW[] = {'A',0};
static const WCHAR colorW[] = {'H','R','E','F',0};
- return do_attribute_tag_format(ctx, jsthis, flags, dp, retv, ei, sp, fontW, colorW);
+ return do_attribute_tag_format(ctx, jsthis, argc, argv, r, fontW, colorW);
}
/* ECMA-262 3rd Edition 15.5.4.10 */
-static HRESULT String_match(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT String_match(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- const WCHAR *str;
- DispatchEx *regexp;
- VARIANT *arg_var;
- DWORD length;
- BSTR val_str = NULL;
- HRESULT hres = S_OK;
+ jsdisp_t *regexp = NULL;
+ jsstr_t *str;
+ HRESULT hres;
TRACE("\n");
- if(!arg_cnt(dp)) {
- if(retv) {
- V_VT(retv) = VT_NULL;
- }
-
+ if(!argc) {
+ if(r)
+ *r = jsval_null();
return S_OK;
}
- arg_var = get_arg(dp, 0);
- switch(V_VT(arg_var)) {
- case VT_DISPATCH:
- regexp = iface_to_jsdisp((IUnknown*)V_DISPATCH(arg_var));
- if(regexp) {
- if(is_class(regexp, JSCLASS_REGEXP))
- break;
+ if(is_object_instance(argv[0])) {
+ regexp = iface_to_jsdisp((IUnknown*)get_object(argv[0]));
+ if(regexp && !is_class(regexp, JSCLASS_REGEXP)) {
jsdisp_release(regexp);
+ regexp = NULL;
}
- default: {
- BSTR match_str;
+ }
- hres = to_string(ctx, arg_var, ei, &match_str);
+ if(!regexp) {
+ jsstr_t *match_str;
+
+ hres = to_string(ctx, argv[0], &match_str);
if(FAILED(hres))
return hres;
- hres = create_regexp(ctx, match_str, SysStringLen(match_str), 0, ®exp);
- SysFreeString(match_str);
+ hres = create_regexp(ctx, match_str, 0, ®exp);
+ jsstr_release(match_str);
if(FAILED(hres))
return hres;
}
- }
- hres = get_string_val(ctx, jsthis, ei, &str, &length, &val_str);
- if(SUCCEEDED(hres)) {
- if(!val_str)
- val_str = SysAllocStringLen(str, length);
- if(val_str)
- hres = regexp_string_match(ctx, regexp, val_str, retv, ei);
- else
- hres = E_OUTOFMEMORY;
- }
+ hres = get_string_val(ctx, jsthis, &str);
+ if(SUCCEEDED(hres))
+ hres = regexp_string_match(ctx, regexp, str, r);
jsdisp_release(regexp);
- SysFreeString(val_str);
+ jsstr_release(str);
return hres;
}
return S_OK;
}
-static HRESULT rep_call(script_ctx_t *ctx, DispatchEx *func, const WCHAR *str, match_result_t *match,
- match_result_t *parens, DWORD parens_cnt, BSTR *ret, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT rep_call(script_ctx_t *ctx, jsdisp_t *func,
+ jsstr_t *str, match_state_t *match, jsstr_t **ret)
{
- DISPPARAMS dp = {NULL, NULL, 0, 0};
- VARIANTARG *args, *arg;
- VARIANT var;
+ jsval_t *argv;
+ unsigned argc;
+ jsval_t val;
+ jsstr_t *tmp_str;
DWORD i;
HRESULT hres = S_OK;
- dp.cArgs = parens_cnt+3;
- dp.rgvarg = args = heap_alloc_zero(sizeof(VARIANT)*dp.cArgs);
- if(!args)
+ argc = match->paren_count+3;
+ argv = heap_alloc_zero(sizeof(*argv)*argc);
+ if(!argv)
return E_OUTOFMEMORY;
- arg = get_arg(&dp,0);
- V_VT(arg) = VT_BSTR;
- V_BSTR(arg) = SysAllocStringLen(match->str, match->len);
- if(!V_BSTR(arg))
+ tmp_str = jsstr_alloc_len(match->cp-match->match_len, match->match_len);
+ if(!tmp_str)
hres = E_OUTOFMEMORY;
+ argv[0] = jsval_string(tmp_str);
if(SUCCEEDED(hres)) {
- for(i=0; i < parens_cnt; i++) {
- arg = get_arg(&dp,i+1);
- V_VT(arg) = VT_BSTR;
- V_BSTR(arg) = SysAllocStringLen(parens[i].str, parens[i].len);
- if(!V_BSTR(arg)) {
+ 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);
+ else
+ tmp_str = jsstr_empty();
+ if(!tmp_str) {
hres = E_OUTOFMEMORY;
break;
}
+ argv[i+1] = jsval_string(tmp_str);
}
}
if(SUCCEEDED(hres)) {
- arg = get_arg(&dp,parens_cnt+1);
- V_VT(arg) = VT_I4;
- V_I4(arg) = match->str - str;
-
- arg = get_arg(&dp,parens_cnt+2);
- V_VT(arg) = VT_BSTR;
- V_BSTR(arg) = SysAllocString(str);
- if(!V_BSTR(arg))
- hres = E_OUTOFMEMORY;
+ argv[match->paren_count+1] = jsval_number(match->cp-str->str - match->match_len);
+ argv[match->paren_count+2] = jsval_string(str);
}
if(SUCCEEDED(hres))
- hres = jsdisp_call_value(func, DISPATCH_METHOD, &dp, &var, ei, caller);
+ hres = jsdisp_call_value(func, NULL, DISPATCH_METHOD, argc, argv, &val);
- for(i=0; i < parens_cnt+3; i++) {
- if(i != parens_cnt+1)
- SysFreeString(V_BSTR(get_arg(&dp,i)));
- }
- heap_free(args);
+ for(i=0; i <= match->paren_count; i++)
+ jsstr_release(get_string(argv[i]));
+ heap_free(argv);
if(FAILED(hres))
return hres;
- hres = to_string(ctx, &var, ei, ret);
- VariantClear(&var);
+ hres = to_string(ctx, val, ret);
+ jsval_release(val);
return hres;
}
/* ECMA-262 3rd Edition 15.5.4.11 */
-static HRESULT String_replace(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+static HRESULT String_replace(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- const WCHAR *str;
- DWORD parens_cnt = 0, parens_size=0, rep_len=0, length;
- BSTR rep_str = NULL, match_str = NULL, ret_str, val_str;
- DispatchEx *rep_func = NULL, *regexp = NULL;
- match_result_t *parens = NULL, match = {NULL,0}, **parens_ptr = &parens;
+ DWORD rep_len=0;
+ jsstr_t *rep_str = NULL, *match_str = NULL, *str;
+ 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;
- VARIANT *arg_var;
+ DWORD re_flags = REM_NO_CTX_UPDATE|REM_ALLOC_RESULT;
HRESULT hres = S_OK;
TRACE("\n");
- hres = get_string_val(ctx, jsthis, ei, &str, &length, &val_str);
+ hres = get_string_val(ctx, jsthis, &str);
if(FAILED(hres))
return hres;
- if(!arg_cnt(dp)) {
- if(retv) {
- if(!val_str) {
- val_str = SysAllocStringLen(str, length);
- if(!val_str)
- return E_OUTOFMEMORY;
- }
-
- V_VT(retv) = VT_BSTR;
- V_BSTR(retv) = val_str;
- }
+ if(!argc) {
+ if(r)
+ *r = jsval_string(str);
+ else
+ jsstr_release(str);
return S_OK;
}
- arg_var = get_arg(dp, 0);
- switch(V_VT(arg_var)) {
- case VT_DISPATCH:
- regexp = iface_to_jsdisp((IUnknown*)V_DISPATCH(arg_var));
- if(regexp) {
- if(is_class(regexp, JSCLASS_REGEXP)) {
- break;
- }else {
- jsdisp_release(regexp);
- regexp = NULL;
- }
+ if(is_object_instance(argv[0])) {
+ regexp = iface_to_jsdisp((IUnknown*)get_object(argv[0]));
+ if(regexp && !is_class(regexp, JSCLASS_REGEXP)) {
+ jsdisp_release(regexp);
+ regexp = NULL;
}
+ }
- default:
- hres = to_string(ctx, arg_var, ei, &match_str);
+ if(!regexp) {
+ hres = to_string(ctx, argv[0], &match_str);
if(FAILED(hres)) {
- SysFreeString(val_str);
+ jsstr_release(str);
return hres;
}
}
- if(arg_cnt(dp) >= 2) {
- arg_var = get_arg(dp,1);
- switch(V_VT(arg_var)) {
- case VT_DISPATCH:
- rep_func = iface_to_jsdisp((IUnknown*)V_DISPATCH(arg_var));
- if(rep_func) {
- if(is_class(rep_func, JSCLASS_FUNCTION)) {
- break;
- }else {
- jsdisp_release(rep_func);
- rep_func = NULL;
- }
+ if(argc >= 2) {
+ if(is_object_instance(argv[1])) {
+ rep_func = iface_to_jsdisp((IUnknown*)get_object(argv[1]));
+ if(rep_func && !is_class(rep_func, JSCLASS_FUNCTION)) {
+ jsdisp_release(rep_func);
+ rep_func = NULL;
}
+ }
- default:
- hres = to_string(ctx, arg_var, ei, &rep_str);
- if(FAILED(hres))
- break;
-
- rep_len = SysStringLen(rep_str);
- if(!strchrW(rep_str, '$'))
- parens_ptr = NULL;
+ if(!rep_func) {
+ hres = to_string(ctx, argv[1], &rep_str);
+ if(SUCCEEDED(hres))
+ rep_len = jsstr_length(rep_str);
}
}
if(SUCCEEDED(hres)) {
- const WCHAR *cp, *ecp;
-
- cp = ecp = str;
+ const WCHAR *ecp = str->str;
while(1) {
if(regexp) {
- hres = regexp_match_next(ctx, regexp, re_flags, str, length, &cp, parens_ptr,
- &parens_size, &parens_cnt, &match);
- re_flags |= REM_CHECK_GLOBAL;
+ hres = regexp_match_next(ctx, regexp, re_flags, str, &match);
+ re_flags = (re_flags | REM_CHECK_GLOBAL) & (~REM_ALLOC_RESULT);
if(hres == S_FALSE) {
hres = S_OK;
}
if(FAILED(hres))
break;
+
+ last_match.cp = match->cp;
+ last_match.match_len = match->match_len;
}else {
- match.str = strstrW(cp, match_str);
- if(!match.str)
+ if(re_flags & REM_ALLOC_RESULT) {
+ re_flags &= ~REM_ALLOC_RESULT;
+ match = &last_match;
+ match->cp = str->str;
+ }
+
+ match->cp = strstrW(match->cp, match_str->str);
+ if(!match->cp)
break;
- match.len = SysStringLen(match_str);
- cp = match.str+match.len;
+ match->match_len = jsstr_length(match_str);
+ match->cp += match->match_len;
}
- hres = strbuf_append(&ret, ecp, match.str-ecp);
- ecp = match.str+match.len;
+ hres = strbuf_append(&ret, ecp, match->cp-ecp-match->match_len);
+ ecp = match->cp;
if(FAILED(hres))
break;
if(rep_func) {
- BSTR cstr;
+ jsstr_t *cstr;
- hres = rep_call(ctx, rep_func, str, &match, parens, parens_cnt, &cstr, ei, caller);
+ hres = rep_call(ctx, rep_func, str, match, &cstr);
if(FAILED(hres))
break;
- hres = strbuf_append(&ret, cstr, SysStringLen(cstr));
- SysFreeString(cstr);
+ hres = strbuf_append(&ret, cstr->str, jsstr_length(cstr));
+ jsstr_release(cstr);
if(FAILED(hres))
break;
}else if(rep_str && regexp) {
- const WCHAR *ptr = rep_str, *ptr2;
+ const WCHAR *ptr = rep_str->str, *ptr2;
while((ptr2 = strchrW(ptr, '$'))) {
hres = strbuf_append(&ret, ptr, ptr2-ptr);
ptr = ptr2+2;
break;
case '&':
- hres = strbuf_append(&ret, match.str, match.len);
+ hres = strbuf_append(&ret, match->cp-match->match_len, match->match_len);
ptr = ptr2+2;
break;
case '`':
- hres = strbuf_append(&ret, str, match.str-str);
+ hres = strbuf_append(&ret, str->str, match->cp-str->str-match->match_len);
ptr = ptr2+2;
break;
case '\'':
- hres = strbuf_append(&ret, ecp, (str+length)-ecp);
+ hres = strbuf_append(&ret, ecp, (str->str+jsstr_length(str))-ecp);
ptr = ptr2+2;
break;
default: {
}
idx = ptr2[1] - '0';
- if(isdigitW(ptr2[2]) && idx*10 + (ptr2[2]-'0') <= parens_cnt) {
+ if(isdigitW(ptr2[2]) && idx*10 + (ptr2[2]-'0') <= match->paren_count) {
idx = idx*10 + (ptr[2]-'0');
ptr = ptr2+3;
- }else if(idx && idx <= parens_cnt) {
+ }else if(idx && idx <= match->paren_count) {
ptr = ptr2+2;
}else {
hres = strbuf_append(&ret, ptr2, 1);
break;
}
- hres = strbuf_append(&ret, parens[idx-1].str, parens[idx-1].len);
+ if(match->parens[idx-1].index != -1)
+ hres = strbuf_append(&ret, str->str+match->parens[idx-1].index,
+ match->parens[idx-1].length);
}
}
}
if(SUCCEEDED(hres))
- hres = strbuf_append(&ret, ptr, (rep_str+rep_len)-ptr);
+ hres = strbuf_append(&ret, ptr, (rep_str->str+rep_len)-ptr);
if(FAILED(hres))
break;
}else if(rep_str) {
- hres = strbuf_append(&ret, rep_str, rep_len);
+ hres = strbuf_append(&ret, rep_str->str, rep_len);
if(FAILED(hres))
break;
}else {
if(FAILED(hres))
break;
}
+
+ if(!regexp)
+ break;
+ else if(!match->match_len)
+ match->cp++;
}
if(SUCCEEDED(hres))
- hres = strbuf_append(&ret, ecp, (str+length)-ecp);
+ hres = strbuf_append(&ret, ecp, str->str+jsstr_length(str)-ecp);
}
if(rep_func)
jsdisp_release(rep_func);
- SysFreeString(rep_str);
- SysFreeString(match_str);
- heap_free(parens);
-
- if(SUCCEEDED(hres) && match.str && regexp) {
- if(!val_str)
- val_str = SysAllocStringLen(str, length);
- if(val_str) {
- SysFreeString(ctx->last_match);
- ctx->last_match = val_str;
- val_str = NULL;
- ctx->last_match_index = match.str-str;
- ctx->last_match_length = match.len;
- }else {
- hres = E_OUTOFMEMORY;
- }
+ if(rep_str)
+ jsstr_release(rep_str);
+ if(match_str)
+ jsstr_release(match_str);
+ 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_length = last_match.match_len;
}
if(regexp)
jsdisp_release(regexp);
- SysFreeString(val_str);
+ jsstr_release(str);
+
+ if(SUCCEEDED(hres) && r) {
+ jsstr_t *ret_str;
- if(SUCCEEDED(hres) && retv) {
- ret_str = SysAllocStringLen(ret.buf, ret.len);
+ ret_str = jsstr_alloc_len(ret.buf, ret.len);
if(!ret_str)
return E_OUTOFMEMORY;
- V_VT(retv) = VT_BSTR;
- V_BSTR(retv) = ret_str;
- TRACE("= %s\n", debugstr_w(ret_str));
+ TRACE("= %s\n", debugstr_jsstr(ret_str));
+ *r = jsval_string(ret_str);
}
heap_free(ret.buf);
return hres;
}
-static HRESULT String_search(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT String_search(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- DispatchEx *regexp = NULL;
- const WCHAR *str, *cp;
- match_result_t match;
- VARIANT *arg;
- DWORD length;
- BSTR val_str;
+ jsdisp_t *regexp = NULL;
+ jsstr_t *str;
+ match_state_t match, *match_ptr = &match;
HRESULT hres;
TRACE("\n");
- hres = get_string_val(ctx, jsthis, ei, &str, &length, &val_str);
+ hres = get_string_val(ctx, jsthis, &str);
if(FAILED(hres))
return hres;
- if(!arg_cnt(dp)) {
- if(retv)
- V_VT(retv) = VT_NULL;
- SysFreeString(val_str);
+ if(!argc) {
+ if(r)
+ *r = jsval_null();
+ jsstr_release(str);
return S_OK;
}
- arg = get_arg(dp,0);
- if(V_VT(arg) == VT_DISPATCH) {
- regexp = iface_to_jsdisp((IUnknown*)V_DISPATCH(arg));
- if(regexp) {
- if(!is_class(regexp, JSCLASS_REGEXP)) {
- jsdisp_release(regexp);
- regexp = NULL;
- }
+ if(is_object_instance(argv[0])) {
+ regexp = iface_to_jsdisp((IUnknown*)get_object(argv[0]));
+ if(regexp && !is_class(regexp, JSCLASS_REGEXP)) {
+ jsdisp_release(regexp);
+ regexp = NULL;
}
}
if(!regexp) {
- hres = create_regexp_var(ctx, arg, NULL, ®exp);
+ hres = create_regexp_var(ctx, argv[0], NULL, ®exp);
if(FAILED(hres)) {
- SysFreeString(val_str);
+ jsstr_release(str);
return hres;
}
}
- cp = str;
- hres = regexp_match_next(ctx, regexp, REM_RESET_INDEX, str, length, &cp, NULL, NULL, NULL, &match);
- SysFreeString(val_str);
+ match.cp = str->str;
+ hres = regexp_match_next(ctx, regexp, REM_RESET_INDEX|REM_NO_PARENS, str, &match_ptr);
+ jsstr_release(str);
jsdisp_release(regexp);
if(FAILED(hres))
return hres;
- if(retv) {
- V_VT(retv) = VT_I4;
- V_I4(retv) = hres == S_OK ? match.str-str : -1;
- }
+ if(r)
+ *r = jsval_number(hres == S_OK ? match.cp-match.match_len-str->str : -1);
return S_OK;
}
/* ECMA-262 3rd Edition 15.5.4.13 */
-static HRESULT String_slice(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT String_slice(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- const WCHAR *str;
- BSTR val_str;
- DWORD length;
- INT start=0, end;
- VARIANT v;
+ int start=0, end, length;
+ jsstr_t *str;
+ double d;
HRESULT hres;
TRACE("\n");
- hres = get_string_val(ctx, jsthis, ei, &str, &length, &val_str);
+ hres = get_string_val(ctx, jsthis, &str);
if(FAILED(hres))
return hres;
- if(arg_cnt(dp)) {
- hres = to_integer(ctx, get_arg(dp,0), ei, &v);
+ length = jsstr_length(str);
+ if(argc) {
+ hres = to_integer(ctx, argv[0], &d);
if(FAILED(hres)) {
- SysFreeString(val_str);
+ jsstr_release(str);
return hres;
}
- if(V_VT(&v) == VT_I4) {
- start = V_I4(&v);
+ if(is_int32(d)) {
+ start = d;
if(start < 0) {
start = length + start;
if(start < 0)
}else if(start > length) {
start = length;
}
- }else {
- start = V_R8(&v) < 0.0 ? 0 : length;
+ }else if(d > 0) {
+ start = length;
}
- }else {
- start = 0;
}
- if(arg_cnt(dp) >= 2) {
- hres = to_integer(ctx, get_arg(dp,1), ei, &v);
+ if(argc >= 2) {
+ hres = to_integer(ctx, argv[1], &d);
if(FAILED(hres)) {
- SysFreeString(val_str);
+ jsstr_release(str);
return hres;
}
- if(V_VT(&v) == VT_I4) {
- end = V_I4(&v);
+ if(is_int32(d)) {
+ end = d;
if(end < 0) {
end = length + end;
if(end < 0)
end = length;
}
}else {
- end = V_R8(&v) < 0.0 ? 0 : length;
+ end = d < 0.0 ? 0 : length;
}
}else {
end = length;
if(end < start)
end = start;
- if(retv) {
- BSTR retstr = SysAllocStringLen(str+start, end-start);
+ if(r) {
+ jsstr_t *retstr = jsstr_substr(str, start, end-start);
if(!retstr) {
- SysFreeString(val_str);
+ jsstr_release(str);
return E_OUTOFMEMORY;
}
- V_VT(retv) = VT_BSTR;
- V_BSTR(retv) = retstr;
+ *r = jsval_string(retstr);
}
- SysFreeString(val_str);
+ jsstr_release(str);
return S_OK;
}
-static HRESULT String_small(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT String_small(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
static const WCHAR smalltagW[] = {'S','M','A','L','L',0};
- return do_attributeless_tag_format(ctx, jsthis, flags, dp, retv, ei, sp, smalltagW);
+ return do_attributeless_tag_format(ctx, jsthis, r, smalltagW);
}
-static HRESULT String_split(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT String_split(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- match_result_t *match_result = NULL;
- DWORD length, match_cnt, i, match_len = 0;
- const WCHAR *str, *ptr, *ptr2;
- BOOL use_regexp = FALSE;
- VARIANT *arg, var;
- DispatchEx *array;
- BSTR val_str, match_str = NULL;
+ match_state_t match_result, *match_ptr = &match_result;
+ DWORD length, i, match_len = 0;
+ const WCHAR *ptr, *ptr2;
+ unsigned limit = UINT32_MAX;
+ jsdisp_t *array, *regexp = NULL;
+ jsstr_t *str, *match_str = NULL, *tmp_str;
HRESULT hres;
TRACE("\n");
- if(arg_cnt(dp) != 1) {
- FIXME("unsupported args\n");
+ if(argc != 1 && argc != 2) {
+ FIXME("unsupported argc %u\n", argc);
return E_NOTIMPL;
}
- hres = get_string_val(ctx, jsthis, ei, &str, &length, &val_str);
+ hres = get_string_val(ctx, jsthis, &str);
if(FAILED(hres))
return hres;
- arg = get_arg(dp, 0);
- switch(V_VT(arg)) {
- case VT_DISPATCH: {
- DispatchEx *regexp;
+ length = jsstr_length(str);
+
+ if(argc > 1 && !is_undefined(argv[1])) {
+ hres = to_uint32(ctx, argv[1], &limit);
+ if(FAILED(hres)) {
+ jsstr_release(str);
+ return hres;
+ }
+ }
- regexp = iface_to_jsdisp((IUnknown*)V_DISPATCH(arg));
+ if(is_object_instance(argv[0])) {
+ regexp = iface_to_jsdisp((IUnknown*)get_object(argv[0]));
if(regexp) {
- if(is_class(regexp, JSCLASS_REGEXP)) {
- use_regexp = TRUE;
- hres = regexp_match(ctx, regexp, str, length, TRUE, &match_result, &match_cnt);
+ if(!is_class(regexp, JSCLASS_REGEXP)) {
jsdisp_release(regexp);
- if(FAILED(hres)) {
- SysFreeString(val_str);
- return hres;
- }
- break;
+ regexp = NULL;
}
- jsdisp_release(regexp);
}
}
- default:
- hres = to_string(ctx, arg, ei, &match_str);
+
+ if(!regexp) {
+ hres = to_string(ctx, argv[0], &match_str);
if(FAILED(hres)) {
- SysFreeString(val_str);
+ jsstr_release(str);
return hres;
}
- match_len = SysStringLen(match_str);
+ match_len = jsstr_length(match_str);
if(!match_len) {
- SysFreeString(match_str);
+ jsstr_release(match_str);
match_str = NULL;
}
}
hres = create_array(ctx, 0, &array);
if(SUCCEEDED(hres)) {
- ptr = str;
- for(i=0;; i++) {
- if(use_regexp) {
- if(i == match_cnt)
+ ptr = str->str;
+ match_result.cp = str->str;
+ for(i=0; i<limit; i++) {
+ if(regexp) {
+ hres = regexp_match_next(ctx, regexp, REM_NO_PARENS, str, &match_ptr);
+ if(hres != S_OK)
break;
- ptr2 = match_result[i].str;
+ ptr2 = match_result.cp - match_result.match_len;
}else if(match_str) {
- ptr2 = strstrW(ptr, match_str);
+ ptr2 = strstrW(ptr, match_str->str);
if(!ptr2)
break;
}else {
ptr2 = ptr+1;
}
- V_VT(&var) = VT_BSTR;
- V_BSTR(&var) = SysAllocStringLen(ptr, ptr2-ptr);
- if(!V_BSTR(&var)) {
+ tmp_str = jsstr_alloc_len(ptr, ptr2-ptr);
+ if(!tmp_str) {
hres = E_OUTOFMEMORY;
break;
}
- hres = jsdisp_propput_idx(array, i, &var, ei, sp);
- SysFreeString(V_BSTR(&var));
+ hres = jsdisp_propput_idx(array, i, jsval_string(tmp_str));
+ jsstr_release(tmp_str);
if(FAILED(hres))
break;
- if(use_regexp)
- ptr = match_result[i].str + match_result[i].len;
+ if(regexp)
+ ptr = match_result.cp;
else if(match_str)
ptr = ptr2 + match_len;
else
}
}
- if(SUCCEEDED(hres) && (match_str || use_regexp)) {
- DWORD len = (str+length) - ptr;
+ if(SUCCEEDED(hres) && (match_str || regexp) && i<limit) {
+ DWORD len = (str->str+length) - ptr;
if(len || match_str) {
- V_VT(&var) = VT_BSTR;
- V_BSTR(&var) = SysAllocStringLen(ptr, len);
+ tmp_str = jsstr_alloc_len(ptr, len);
- if(V_BSTR(&var)) {
- hres = jsdisp_propput_idx(array, i, &var, ei, sp);
- SysFreeString(V_BSTR(&var));
+ if(tmp_str) {
+ hres = jsdisp_propput_idx(array, i, jsval_string(tmp_str));
+ jsstr_release(tmp_str);
}else {
hres = E_OUTOFMEMORY;
}
}
}
- SysFreeString(match_str);
- SysFreeString(val_str);
- heap_free(match_result);
+ if(regexp)
+ jsdisp_release(regexp);
+ if(match_str)
+ jsstr_release(match_str);
+ jsstr_release(str);
- if(SUCCEEDED(hres) && retv) {
- V_VT(retv) = VT_DISPATCH;
- V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(array);
- }else {
+ if(SUCCEEDED(hres) && r)
+ *r = jsval_obj(array);
+ else
jsdisp_release(array);
- }
return hres;
}
-static HRESULT String_strike(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT String_strike(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
static const WCHAR striketagW[] = {'S','T','R','I','K','E',0};
- return do_attributeless_tag_format(ctx, jsthis, flags, dp, retv, ei, sp, striketagW);
+ return do_attributeless_tag_format(ctx, jsthis, r, striketagW);
}
-static HRESULT String_sub(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT String_sub(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
static const WCHAR subtagW[] = {'S','U','B',0};
- return do_attributeless_tag_format(ctx, jsthis, flags, dp, retv, ei, sp, subtagW);
+ return do_attributeless_tag_format(ctx, jsthis, r, subtagW);
}
/* ECMA-262 3rd Edition 15.5.4.15 */
-static HRESULT String_substring(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT String_substring(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- const WCHAR *str;
- BSTR val_str;
- INT start=0, end;
- DWORD length;
- VARIANT v;
+ INT start=0, end, length;
+ jsstr_t *str;
+ double d;
HRESULT hres;
TRACE("\n");
- hres = get_string_val(ctx, jsthis, ei, &str, &length, &val_str);
+ hres = get_string_val(ctx, jsthis, &str);
if(FAILED(hres))
return hres;
- if(arg_cnt(dp) >= 1) {
- hres = to_integer(ctx, get_arg(dp,0), ei, &v);
+ length = jsstr_length(str);
+ if(argc >= 1) {
+ hres = to_integer(ctx, argv[0], &d);
if(FAILED(hres)) {
- SysFreeString(val_str);
+ jsstr_release(str);
return hres;
}
- if(V_VT(&v) == VT_I4) {
- start = V_I4(&v);
- if(start < 0)
- start = 0;
- else if(start >= length)
- start = length;
- }else {
- start = V_R8(&v) < 0.0 ? 0 : length;
- }
+ if(d >= 0)
+ start = is_int32(d) ? min(length, d) : length;
}
- if(arg_cnt(dp) >= 2) {
- hres = to_integer(ctx, get_arg(dp,1), ei, &v);
+ if(argc >= 2) {
+ hres = to_integer(ctx, argv[1], &d);
if(FAILED(hres)) {
- SysFreeString(val_str);
+ jsstr_release(str);
return hres;
}
- if(V_VT(&v) == VT_I4) {
- end = V_I4(&v);
- if(end < 0)
- end = 0;
- else if(end > length)
- end = length;
- }else {
- end = V_R8(&v) < 0.0 ? 0 : length;
- }
+ if(d >= 0)
+ end = is_int32(d) ? min(length, d) : length;
+ else
+ end = 0;
}else {
end = length;
}
end = tmp;
}
- if(retv) {
- V_VT(retv) = VT_BSTR;
- V_BSTR(retv) = SysAllocStringLen(str+start, end-start);
- if(!V_BSTR(retv)) {
- SysFreeString(val_str);
- return E_OUTOFMEMORY;
- }
+ if(r) {
+ jsstr_t *ret = jsstr_substr(str, start, end-start);
+ if(ret)
+ *r = jsval_string(ret);
+ else
+ hres = E_OUTOFMEMORY;
}
- SysFreeString(val_str);
- return S_OK;
+ jsstr_release(str);
+ return hres;
}
/* ECMA-262 3rd Edition B.2.3 */
-static HRESULT String_substr(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT String_substr(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- BSTR val_str;
- const WCHAR *str;
- INT start=0, len;
- DWORD length;
- VARIANT v;
+ int start=0, len, length;
+ jsstr_t *str;
+ double d;
HRESULT hres;
TRACE("\n");
- hres = get_string_val(ctx, jsthis, ei, &str, &length, &val_str);
+ hres = get_string_val(ctx, jsthis, &str);
if(FAILED(hres))
return hres;
- if(arg_cnt(dp) >= 1) {
- hres = to_integer(ctx, get_arg(dp,0), ei, &v);
+ length = jsstr_length(str);
+ if(argc >= 1) {
+ hres = to_integer(ctx, argv[0], &d);
if(FAILED(hres)) {
- SysFreeString(val_str);
+ jsstr_release(str);
return hres;
}
- if(V_VT(&v) == VT_I4) {
- start = V_I4(&v);
- if(start < 0)
- start = 0;
- else if(start >= length)
- start = length;
- }else {
- start = V_R8(&v) < 0.0 ? 0 : length;
- }
+ if(d >= 0)
+ start = is_int32(d) ? min(length, d) : length;
}
- if(arg_cnt(dp) >= 2) {
- hres = to_integer(ctx, get_arg(dp,1), ei, &v);
+ if(argc >= 2) {
+ hres = to_integer(ctx, argv[1], &d);
if(FAILED(hres)) {
- SysFreeString(val_str);
+ jsstr_release(str);
return hres;
}
- if(V_VT(&v) == VT_I4) {
- len = V_I4(&v);
- if(len < 0)
- len = 0;
- else if(len > length-start)
- len = length-start;
- }else {
- len = V_R8(&v) < 0.0 ? 0 : length-start;
- }
+ if(d >= 0.0)
+ len = is_int32(d) ? min(length-start, d) : length-start;
+ else
+ len = 0;
}else {
len = length-start;
}
hres = S_OK;
- if(retv) {
- V_VT(retv) = VT_BSTR;
- V_BSTR(retv) = SysAllocStringLen(str+start, len);
- if(!V_BSTR(retv))
+ if(r) {
+ jsstr_t *ret = jsstr_substr(str, start, len);
+ if(ret)
+ *r = jsval_string(ret);
+ else
hres = E_OUTOFMEMORY;
}
- SysFreeString(val_str);
+ jsstr_release(str);
return hres;
}
-static HRESULT String_sup(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT String_sup(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
static const WCHAR suptagW[] = {'S','U','P',0};
- return do_attributeless_tag_format(ctx, jsthis, flags, dp, retv, ei, sp, suptagW);
+ return do_attributeless_tag_format(ctx, jsthis, r, suptagW);
}
-static HRESULT String_toLowerCase(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT String_toLowerCase(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- const WCHAR* str;
- DWORD length;
- BSTR val_str;
+ jsstr_t *str;
HRESULT hres;
TRACE("\n");
- hres = get_string_val(ctx, jsthis, ei, &str, &length, &val_str);
+ hres = get_string_val(ctx, jsthis, &str);
if(FAILED(hres))
return hres;
- if(retv) {
- if(!val_str) {
- val_str = SysAllocStringLen(str, length);
- if(!val_str)
- return E_OUTOFMEMORY;
- }
+ if(r) {
+ jsstr_t *ret;
- strlwrW(val_str);
+ ret = jsstr_alloc_buf(jsstr_length(str));
+ if(!ret) {
+ jsstr_release(str);
+ return E_OUTOFMEMORY;
+ }
- V_VT(retv) = VT_BSTR;
- V_BSTR(retv) = val_str;
+ jsstr_flush(str, ret->str);
+ strlwrW(ret->str);
+ *r = jsval_string(ret);
}
- else SysFreeString(val_str);
+ jsstr_release(str);
return S_OK;
}
-static HRESULT String_toUpperCase(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT String_toUpperCase(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
- const WCHAR* str;
- DWORD length;
- BSTR val_str;
+ jsstr_t *str;
HRESULT hres;
TRACE("\n");
- hres = get_string_val(ctx, jsthis, ei, &str, &length, &val_str);
+ hres = get_string_val(ctx, jsthis, &str);
if(FAILED(hres))
return hres;
- if(retv) {
- if(!val_str) {
- val_str = SysAllocStringLen(str, length);
- if(!val_str)
- return E_OUTOFMEMORY;
- }
+ if(r) {
+ jsstr_t *ret;
- struprW(val_str);
+ ret = jsstr_alloc_buf(jsstr_length(str));
+ if(!ret) {
+ jsstr_release(str);
+ return E_OUTOFMEMORY;
+ }
- V_VT(retv) = VT_BSTR;
- V_BSTR(retv) = val_str;
+ jsstr_flush(str, ret->str);
+ struprW(ret->str);
+ *r = jsval_string(ret);
}
- else SysFreeString(val_str);
+ jsstr_release(str);
return S_OK;
}
-static HRESULT String_toLocaleLowerCase(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT String_toLocaleLowerCase(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
FIXME("\n");
return E_NOTIMPL;
}
-static HRESULT String_toLocaleUpperCase(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT String_toLocaleUpperCase(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
FIXME("\n");
return E_NOTIMPL;
}
-static HRESULT String_localeCompare(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT String_localeCompare(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
FIXME("\n");
return E_NOTIMPL;
}
-static HRESULT String_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT String_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
StringInstance *This = string_from_vdisp(jsthis);
switch(flags) {
case INVOKE_FUNC:
- return throw_type_error(ctx, ei, IDS_NOT_FUNC, NULL);
+ return throw_type_error(ctx, JS_E_FUNCTION_EXPECTED, NULL);
case DISPATCH_PROPERTYGET: {
- BSTR str = SysAllocString(This->str);
- if(!str)
- return E_OUTOFMEMORY;
-
- V_VT(retv) = VT_BSTR;
- V_BSTR(retv) = str;
+ *r = jsval_string(jsstr_addref(This->str));
break;
}
default:
return S_OK;
}
-static void String_destructor(DispatchEx *dispex)
+static void String_destructor(jsdisp_t *dispex)
{
StringInstance *This = (StringInstance*)dispex;
- heap_free(This->str);
+ jsstr_release(This->str);
heap_free(This);
}
+static unsigned String_idx_length(jsdisp_t *jsdisp)
+{
+ StringInstance *string = (StringInstance*)jsdisp;
+
+ /*
+ * NOTE: For invoke version < 2, indexed array is not implemented at all.
+ * Newer jscript.dll versions implement it on string type, not class,
+ * which is not how it should work according to spec. IE9 implements it
+ * properly, but it uses its own JavaScript engine inside MSHTML. We
+ * implement it here, but in the way IE9 and spec work.
+ */
+ return string->dispex.ctx->version < 2 ? 0 : jsstr_length(string->str);
+}
+
+static HRESULT String_idx_get(jsdisp_t *jsdisp, unsigned idx, jsval_t *r)
+{
+ StringInstance *string = (StringInstance*)jsdisp;
+ jsstr_t *ret;
+
+ ret = jsstr_substr(string->str, idx, 1);
+ if(!ret)
+ return E_OUTOFMEMORY;
+
+ TRACE("%p[%u] = %s\n", string, idx, debugstr_jsstr(ret));
+
+ *r = jsval_string(ret);
+ return S_OK;
+}
+
static const builtin_prop_t String_props[] = {
{anchorW, String_anchor, PROPF_METHOD|1},
{bigW, String_big, PROPF_METHOD},
NULL
};
+static const builtin_prop_t StringInst_props[] = {
+ {lengthW, String_length, 0}
+};
+
+static const builtin_info_t StringInst_info = {
+ JSCLASS_STRING,
+ {NULL, String_value, 0},
+ sizeof(StringInst_props)/sizeof(*StringInst_props),
+ StringInst_props,
+ String_destructor,
+ NULL,
+ String_idx_length,
+ String_idx_get
+};
+
/* ECMA-262 3rd Edition 15.5.3.2 */
static HRESULT StringConstr_fromCharCode(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
- DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+ unsigned argc, jsval_t *argv, jsval_t *r)
{
DWORD i, code;
- BSTR ret;
+ jsstr_t *ret;
HRESULT hres;
- ret = SysAllocStringLen(NULL, arg_cnt(dp));
+ TRACE("\n");
+
+ ret = jsstr_alloc_buf(argc);
if(!ret)
return E_OUTOFMEMORY;
- for(i=0; i<arg_cnt(dp); i++) {
- hres = to_uint32(ctx, get_arg(dp, i), ei, &code);
+ for(i=0; i<argc; i++) {
+ hres = to_uint32(ctx, argv[i], &code);
if(FAILED(hres)) {
- SysFreeString(ret);
+ jsstr_release(ret);
return hres;
}
- ret[i] = code;
- }
-
- if(retv) {
- V_VT(retv) = VT_BSTR;
- V_BSTR(retv) = ret;
+ ret->str[i] = code;
}
- else SysFreeString(ret);
+ if(r)
+ *r = jsval_string(ret);
+ else
+ jsstr_release(ret);
return S_OK;
}
-static HRESULT StringConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+static HRESULT StringConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
{
HRESULT hres;
switch(flags) {
case INVOKE_FUNC: {
- BSTR str;
+ jsstr_t *str;
- if(arg_cnt(dp)) {
- hres = to_string(ctx, get_arg(dp, 0), ei, &str);
+ if(argc) {
+ hres = to_string(ctx, argv[0], &str);
if(FAILED(hres))
return hres;
}else {
- str = SysAllocStringLen(NULL, 0);
- if(!str)
- return E_OUTOFMEMORY;
+ str = jsstr_empty();
}
- V_VT(retv) = VT_BSTR;
- V_BSTR(retv) = str;
+ *r = jsval_string(str);
break;
}
case DISPATCH_CONSTRUCT: {
- DispatchEx *ret;
+ jsdisp_t *ret;
- if(arg_cnt(dp)) {
- BSTR str;
+ if(argc) {
+ jsstr_t *str;
- hres = to_string(ctx, get_arg(dp, 0), ei, &str);
+ hres = to_string(ctx, argv[0], &str);
if(FAILED(hres))
return hres;
- hres = create_string(ctx, str, SysStringLen(str), &ret);
- SysFreeString(str);
+ hres = create_string(ctx, str, &ret);
+ jsstr_release(str);
}else {
- hres = create_string(ctx, NULL, 0, &ret);
+ hres = create_string(ctx, jsstr_empty(), &ret);
}
if(FAILED(hres))
return hres;
- V_VT(retv) = VT_DISPATCH;
- V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(ret);
+ *r = jsval_obj(ret);
break;
}
return S_OK;
}
-static HRESULT string_alloc(script_ctx_t *ctx, DispatchEx *object_prototype, StringInstance **ret)
+static HRESULT string_alloc(script_ctx_t *ctx, jsdisp_t *object_prototype, jsstr_t *str, StringInstance **ret)
{
StringInstance *string;
HRESULT hres;
if(object_prototype)
hres = init_dispex(&string->dispex, ctx, &String_info, object_prototype);
else
- hres = init_dispex_from_constr(&string->dispex, ctx, &String_info, ctx->string_constr);
+ hres = init_dispex_from_constr(&string->dispex, ctx, &StringInst_info, ctx->string_constr);
if(FAILED(hres)) {
heap_free(string);
return hres;
}
+ string->str = jsstr_addref(str);
*ret = string;
return S_OK;
}
NULL
};
-HRESULT create_string_constr(script_ctx_t *ctx, DispatchEx *object_prototype, DispatchEx **ret)
+HRESULT create_string_constr(script_ctx_t *ctx, jsdisp_t *object_prototype, jsdisp_t **ret)
{
StringInstance *string;
HRESULT hres;
static const WCHAR StringW[] = {'S','t','r','i','n','g',0};
- hres = string_alloc(ctx, object_prototype, &string);
+ hres = string_alloc(ctx, object_prototype, jsstr_empty(), &string);
if(FAILED(hres))
return hres;
- hres = create_builtin_function(ctx, StringConstr_value, StringW, &StringConstr_info,
+ hres = create_builtin_constructor(ctx, StringConstr_value, StringW, &StringConstr_info,
PROPF_CONSTR|1, &string->dispex, ret);
jsdisp_release(&string->dispex);
return hres;
}
-HRESULT create_string(script_ctx_t *ctx, const WCHAR *str, DWORD len, DispatchEx **ret)
+HRESULT create_string(script_ctx_t *ctx, jsstr_t *str, jsdisp_t **ret)
{
StringInstance *string;
HRESULT hres;
- hres = string_alloc(ctx, NULL, &string);
+ hres = string_alloc(ctx, NULL, str, &string);
if(FAILED(hres))
return hres;
- if(len == -1)
- len = strlenW(str);
-
- string->length = len;
- string->str = heap_alloc((len+1)*sizeof(WCHAR));
- if(!string->str) {
- jsdisp_release(&string->dispex);
- return E_OUTOFMEMORY;
- }
-
- memcpy(string->str, str, len*sizeof(WCHAR));
- string->str[len] = 0;
-
*ret = &string->dispex;
return S_OK;
--- /dev/null
+/*
+ * Copyright 2010 Piotr Caban for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "jscript.h"
+
+#include <wine/debug.h>
+
+WINE_DEFAULT_DEBUG_CHANNEL(jscript);
+
+typedef struct {
+ jsdisp_t dispex;
+
+ SAFEARRAY *safearray;
+} VBArrayInstance;
+
+static const WCHAR dimensionsW[] = {'d','i','m','e','n','s','i','o','n','s',0};
+static const WCHAR getItemW[] = {'g','e','t','I','t','e','m',0};
+static const WCHAR lboundW[] = {'l','b','o','u','n','d',0};
+static const WCHAR toArrayW[] = {'t','o','A','r','r','a','y',0};
+static const WCHAR uboundW[] = {'u','b','o','u','n','d',0};
+
+static inline VBArrayInstance *vbarray_from_vdisp(vdisp_t *vdisp)
+{
+ return (VBArrayInstance*)vdisp->u.jsdisp;
+}
+
+static inline VBArrayInstance *vbarray_this(vdisp_t *jsthis)
+{
+ return is_vclass(jsthis, JSCLASS_VBARRAY) ? vbarray_from_vdisp(jsthis) : NULL;
+}
+
+static HRESULT VBArray_dimensions(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
+{
+ VBArrayInstance *vbarray;
+
+ TRACE("\n");
+
+ vbarray = vbarray_this(vthis);
+ if(!vbarray)
+ return throw_type_error(ctx, JS_E_VBARRAY_EXPECTED, NULL);
+
+ if(r)
+ *r = jsval_number(SafeArrayGetDim(vbarray->safearray));
+ return S_OK;
+}
+
+static HRESULT VBArray_getItem(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
+{
+ VBArrayInstance *vbarray;
+ int i, *indexes;
+ VARIANT out;
+ HRESULT hres;
+
+ TRACE("\n");
+
+ vbarray = vbarray_this(vthis);
+ if(!vbarray)
+ return throw_type_error(ctx, JS_E_VBARRAY_EXPECTED, NULL);
+
+ if(argc < SafeArrayGetDim(vbarray->safearray))
+ return throw_range_error(ctx, JS_E_SUBSCRIPT_OUT_OF_RANGE, NULL);
+
+ indexes = heap_alloc(sizeof(int)*argc);
+ if(!indexes)
+ return E_OUTOFMEMORY;
+
+ for(i=0; i<argc; i++) {
+ hres = to_int32(ctx, argv[i], indexes+i);
+ if(FAILED(hres)) {
+ heap_free(indexes);
+ return hres;
+ }
+ }
+
+ hres = SafeArrayGetElement(vbarray->safearray, indexes, (void*)&out);
+ heap_free(indexes);
+ if(hres == DISP_E_BADINDEX)
+ return throw_range_error(ctx, JS_E_SUBSCRIPT_OUT_OF_RANGE, NULL);
+ else if(FAILED(hres))
+ return hres;
+
+ if(r) {
+ hres = variant_to_jsval(&out, r);
+ VariantClear(&out);
+ }
+ return hres;
+}
+
+static HRESULT VBArray_lbound(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
+{
+ VBArrayInstance *vbarray;
+ int dim;
+ HRESULT hres;
+
+ TRACE("\n");
+
+ vbarray = vbarray_this(vthis);
+ if(!vbarray)
+ return throw_type_error(ctx, JS_E_VBARRAY_EXPECTED, NULL);
+
+ if(argc) {
+ hres = to_int32(ctx, argv[0], &dim);
+ if(FAILED(hres))
+ return hres;
+ } else
+ dim = 1;
+
+ hres = SafeArrayGetLBound(vbarray->safearray, dim, &dim);
+ if(hres == DISP_E_BADINDEX)
+ return throw_range_error(ctx, JS_E_SUBSCRIPT_OUT_OF_RANGE, NULL);
+ else if(FAILED(hres))
+ return hres;
+
+ if(r)
+ *r = jsval_number(dim);
+ return S_OK;
+}
+
+static HRESULT VBArray_toArray(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
+{
+ VBArrayInstance *vbarray;
+ jsdisp_t *array;
+ jsval_t val;
+ VARIANT *v;
+ int i, size = 1, ubound, lbound;
+ HRESULT hres;
+
+ TRACE("\n");
+
+ vbarray = vbarray_this(vthis);
+ if(!vbarray)
+ return throw_type_error(ctx, JS_E_VBARRAY_EXPECTED, NULL);
+
+ for(i=1; i<=SafeArrayGetDim(vbarray->safearray); i++) {
+ SafeArrayGetLBound(vbarray->safearray, i, &lbound);
+ SafeArrayGetUBound(vbarray->safearray, i, &ubound);
+ size *= ubound-lbound+1;
+ }
+
+ hres = SafeArrayAccessData(vbarray->safearray, (void**)&v);
+ if(FAILED(hres))
+ return hres;
+
+ hres = create_array(ctx, 0, &array);
+ if(FAILED(hres)) {
+ SafeArrayUnaccessData(vbarray->safearray);
+ return hres;
+ }
+
+ for(i=0; i<size; i++) {
+ hres = variant_to_jsval(v, &val);
+ if(SUCCEEDED(hres)) {
+ hres = jsdisp_propput_idx(array, i, val);
+ jsval_release(val);
+ }
+ if(FAILED(hres)) {
+ SafeArrayUnaccessData(vbarray->safearray);
+ jsdisp_release(array);
+ return hres;
+ }
+ v++;
+ }
+
+ SafeArrayUnaccessData(vbarray->safearray);
+
+ if(r)
+ *r = jsval_obj(array);
+ else
+ jsdisp_release(array);
+ return S_OK;
+}
+
+static HRESULT VBArray_ubound(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
+{
+ VBArrayInstance *vbarray;
+ int dim;
+ HRESULT hres;
+
+ TRACE("\n");
+
+ vbarray = vbarray_this(vthis);
+ if(!vbarray)
+ return throw_type_error(ctx, JS_E_VBARRAY_EXPECTED, NULL);
+
+ if(argc) {
+ hres = to_int32(ctx, argv[0], &dim);
+ if(FAILED(hres))
+ return hres;
+ } else
+ dim = 1;
+
+ hres = SafeArrayGetUBound(vbarray->safearray, dim, &dim);
+ if(hres == DISP_E_BADINDEX)
+ return throw_range_error(ctx, JS_E_SUBSCRIPT_OUT_OF_RANGE, NULL);
+ else if(FAILED(hres))
+ return hres;
+
+ if(r)
+ *r = jsval_number(dim);
+ return S_OK;
+}
+
+static HRESULT VBArray_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
+{
+ FIXME("\n");
+
+ switch(flags) {
+ default:
+ FIXME("unimplemented flags %x\n", flags);
+ return E_NOTIMPL;
+ }
+
+ return S_OK;
+}
+
+static void VBArray_destructor(jsdisp_t *dispex)
+{
+ VBArrayInstance *vbarray = (VBArrayInstance*)dispex;
+
+ SafeArrayDestroy(vbarray->safearray);
+ heap_free(vbarray);
+}
+
+static const builtin_prop_t VBArray_props[] = {
+ {dimensionsW, VBArray_dimensions, PROPF_METHOD},
+ {getItemW, VBArray_getItem, PROPF_METHOD|1},
+ {lboundW, VBArray_lbound, PROPF_METHOD},
+ {toArrayW, VBArray_toArray, PROPF_METHOD},
+ {uboundW, VBArray_ubound, PROPF_METHOD}
+};
+
+static const builtin_info_t VBArray_info = {
+ JSCLASS_VBARRAY,
+ {NULL, VBArray_value, 0},
+ sizeof(VBArray_props)/sizeof(*VBArray_props),
+ VBArray_props,
+ VBArray_destructor,
+ NULL
+};
+
+static HRESULT alloc_vbarray(script_ctx_t *ctx, jsdisp_t *object_prototype, VBArrayInstance **ret)
+{
+ VBArrayInstance *vbarray;
+ HRESULT hres;
+
+ vbarray = heap_alloc_zero(sizeof(VBArrayInstance));
+ if(!vbarray)
+ return E_OUTOFMEMORY;
+
+ if(object_prototype)
+ hres = init_dispex(&vbarray->dispex, ctx, &VBArray_info, object_prototype);
+ else
+ hres = init_dispex_from_constr(&vbarray->dispex, ctx, &VBArray_info, ctx->vbarray_constr);
+
+ if(FAILED(hres)) {
+ heap_free(vbarray);
+ return hres;
+ }
+
+ *ret = vbarray;
+ return S_OK;
+}
+
+static HRESULT VBArrayConstr_value(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv,
+ jsval_t *r)
+{
+ VBArrayInstance *vbarray;
+ HRESULT hres;
+
+ TRACE("\n");
+
+ switch(flags) {
+ case DISPATCH_METHOD:
+ if(argc<1 || !is_variant(argv[0]) || V_VT(get_variant(argv[0])) != (VT_ARRAY|VT_VARIANT))
+ return throw_type_error(ctx, JS_E_VBARRAY_EXPECTED, NULL);
+
+ return jsval_copy(argv[0], r);
+
+ case DISPATCH_CONSTRUCT:
+ if(argc<1 || !is_variant(argv[0]) || V_VT(get_variant(argv[0])) != (VT_ARRAY|VT_VARIANT))
+ return throw_type_error(ctx, JS_E_VBARRAY_EXPECTED, NULL);
+
+ hres = alloc_vbarray(ctx, NULL, &vbarray);
+ if(FAILED(hres))
+ return hres;
+
+ hres = SafeArrayCopy(V_ARRAY(get_variant(argv[0])), &vbarray->safearray);
+ if(FAILED(hres)) {
+ jsdisp_release(&vbarray->dispex);
+ return hres;
+ }
+
+ *r = jsval_obj(&vbarray->dispex);
+ break;
+
+ default:
+ FIXME("unimplemented flags: %x\n", flags);
+ return E_NOTIMPL;
+ }
+
+ return S_OK;
+}
+
+HRESULT create_vbarray_constr(script_ctx_t *ctx, jsdisp_t *object_prototype, jsdisp_t **ret)
+{
+ VBArrayInstance *vbarray;
+ HRESULT hres;
+
+ static const WCHAR VBArrayW[] = {'V','B','A','r','r','a','y',0};
+
+ hres = alloc_vbarray(ctx, object_prototype, &vbarray);
+ if(FAILED(hres))
+ return hres;
+
+ hres = create_builtin_constructor(ctx, VBArrayConstr_value, VBArrayW, NULL, PROPF_CONSTR|1, &vbarray->dispex, ret);
+
+ jsdisp_release(&vbarray->dispex);
+ return hres;
+}
+
+HRESULT create_vbarray(script_ctx_t *ctx, SAFEARRAY *sa, jsdisp_t **ret)
+{
+ VBArrayInstance *vbarray;
+ HRESULT hres;
+
+ hres = alloc_vbarray(ctx, NULL, &vbarray);
+ if(FAILED(hres))
+ return hres;
+
+ hres = SafeArrayCopy(sa, &vbarray->safearray);
+ if(FAILED(hres)) {
+ jsdisp_release(&vbarray->dispex);
+ return hres;
+ }
+
+ *ret = &vbarray->dispex;
+ return S_OK;
+}
reactos/dll/win32/iphlpapi # Out of sync
reactos/dll/win32/itircl # Synced to Wine-1.5.19
reactos/dll/win32/itss # Synced to Wine-1.5.4
-reactos/dll/win32/jscript # Autosync
+reactos/dll/win32/jscript # Synced to Wine-1.5.26
reactos/dll/win32/loadperf # Synced to Wine-1.5.19
reactos/dll/win32/localspl # Synced to Wine-1.1.14?
reactos/dll/win32/localui # Synced to Wine-1.5.19