Enumerator is an MS extension. This fixes installatiion of VyChat219.msi.
Signed-off-by: Andreas Maier staubim@quantentunnel.de --- dlls/jscript/Makefile.in | 1 + dlls/jscript/enumerator.c | 455 +++++++++++++++++++++++++++++++++++++++++++++ dlls/jscript/global.c | 18 +- dlls/jscript/jscript.h | 10 + dlls/jscript/jsglobal.idl | 3 - dlls/jscript/tests/rsrc.rc | 3 + dlls/jscript/tests/run.c | 1 + 7 files changed, 480 insertions(+), 11 deletions(-) create mode 100644 dlls/jscript/enumerator.c
diff --git a/dlls/jscript/Makefile.in b/dlls/jscript/Makefile.in index 34ed193742..1cc58a5ed6 100644 --- a/dlls/jscript/Makefile.in +++ b/dlls/jscript/Makefile.in @@ -10,6 +10,7 @@ C_SRCS = \ decode.c \ dispex.c \ engine.c \ + enumerator.c \ error.c \ function.c \ global.c \ diff --git a/dlls/jscript/enumerator.c b/dlls/jscript/enumerator.c new file mode 100644 index 0000000000..bd05cdf4da --- /dev/null +++ b/dlls/jscript/enumerator.c @@ -0,0 +1,455 @@ +/* + * Copyright 2019 Andreas Maier + * + * 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 "config.h" +#include "wine/port.h" + +#include <math.h> +#include <assert.h> + +#include "jscript.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(jscript); + +#define DATATYPE_ARRAY 0 +#define DATATYPE_STRINGLIST 1 +#define DATATYPE_DRIVECOLLECTION 2 + +typedef struct { + jsdisp_t dispex; + + int index; + int length; + int datatype; + /* constructor with jsarray e.g. ["A","B"] */ + jsdisp_t *array; + /* constructor with stringlist-interface + methods Items and Count are available. + e.g. StringList or IDriveCollection-Interface */ + IDispatch *stringlist; +} EnumeratorInstance; + +static const WCHAR atEndW[] = {'a','t','E','n','d',0}; +static const WCHAR itemW[] = {'i','t','e','m',0}; +static const WCHAR moveFirstW[] = {'m','o','v','e','F','i','r','s','t',0}; +static const WCHAR moveNextW[] = {'m','o','v','e','N','e','x','t',0}; + +static EXCEPINFO excepinfo; +static HRESULT invoke(IDispatch *pDispatch, LPCSTR szName, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, VARTYPE vtResult) +{ + OLECHAR *name = NULL; + DISPID dispid; + HRESULT hr; + UINT i; + UINT len; + + memset(pVarResult, 0, sizeof(VARIANT)); + VariantInit(pVarResult); + + len = MultiByteToWideChar(CP_ACP, 0, szName, -1, NULL, 0 ); + name = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR) ); + if (!name) return E_FAIL; + MultiByteToWideChar(CP_ACP, 0, szName, -1, name, len ); + hr = IDispatch_GetIDsOfNames(pDispatch, &IID_NULL, &name, 1, LOCALE_USER_DEFAULT, &dispid); + HeapFree(GetProcessHeap(), 0, name); + if (FAILED(hr)) + return hr; + + memset(&excepinfo, 0, sizeof(excepinfo)); + hr = IDispatch_Invoke(pDispatch, dispid, &IID_NULL, LOCALE_NEUTRAL, wFlags, pDispParams, pVarResult, &excepinfo, NULL); + + if ((hr == S_OK) && (vtResult != VT_EMPTY)) + hr = VariantChangeTypeEx(pVarResult, pVarResult, LOCALE_NEUTRAL, 0, vtResult); + + for (i=0; i<pDispParams->cArgs; i++) + VariantClear(&pDispParams->rgvarg[i]); + + return hr; +} + +static HRESULT Dispatch_ItemAllocStr(IDispatch *pStringList, int iIndex, LPWSTR *szString) +{ + VARIANT varresult; + VARIANTARG vararg[1]; + DISPPARAMS dispparams = {vararg, NULL, sizeof(vararg)/sizeof(VARIANTARG), 0}; + UINT charCount; + HRESULT hr; + + *szString = NULL; + + VariantInit(&vararg[0]); + V_VT(&vararg[0]) = VT_I4; + V_I4(&vararg[0]) = iIndex; + + hr = invoke(pStringList, "Item", DISPATCH_PROPERTYGET, &dispparams, &varresult, VT_BSTR); + if (FAILED(hr)) + goto CLEANUP; + + charCount = SysStringLen(V_BSTR(&varresult)) + 1; + *szString = (LPWSTR)malloc(charCount * sizeof(WCHAR)); + if (!(*szString)) + { + hr = ERROR_OUTOFMEMORY; + goto CLEANUP; + } + if (!lstrcpynW(*szString, V_BSTR(&varresult), charCount)) + { + hr = E_FAIL; + goto CLEANUP; + } +CLEANUP: + VariantClear(&varresult); + if (FAILED(hr)) + { + free(*szString); + *szString = NULL; + } + return hr; +} + +static HRESULT Dispatch_Count(IDispatch *pStringList, int *pCount) +{ + VARIANT varresult; + DISPPARAMS dispparams = {NULL, NULL, 0, 0}; + HRESULT hr = invoke(pStringList, "Count", DISPATCH_PROPERTYGET, &dispparams, &varresult, VT_I4); + *pCount = V_I4(&varresult); + VariantClear(&varresult); + return hr; +} + +static inline EnumeratorInstance *enumerator_from_jsdisp(jsdisp_t *jsdisp) +{ + return CONTAINING_RECORD(jsdisp, EnumeratorInstance, dispex); +} + +static inline EnumeratorInstance *enumerator_from_vdisp(vdisp_t *vdisp) +{ + return enumerator_from_jsdisp(vdisp->u.jsdisp); +} + +static inline void enum_set_item_result(EnumeratorInstance *This, jsval_t *r) +{ + HRESULT hres; + WCHAR* item; + + if (!r) + return; + + if ((This->index < 0) || + (This->index >= This->length)) + { + *r = jsval_undefined(); + return; + } + + switch (This->datatype) + { + case DATATYPE_ARRAY: + { + hres = jsdisp_get_idx(This->array, This->index, r); + if (FAILED(hres)) + *r = jsval_undefined(); + break; + } + case DATATYPE_STRINGLIST: + { + hres = Dispatch_ItemAllocStr(This->stringlist, This->index, &item); + if (FAILED(hres)) + { + TRACE("item %d <failed>\n", This->index); + *r = jsval_undefined(); + } else + { + TRACE("item %d %s\n", This->index, debugstr_w(item)); + *r = jsval_string(jsstr_alloc(item)); + free(item); + } + break; + } + case DATATYPE_DRIVECOLLECTION: + { + FIXME("getitem for drivecollection not implemented!\n"); + *r = jsval_undefined(); + break; + } + default: + { + *r = jsval_undefined(); + } + } +} + +static void Enumerator_destructor(jsdisp_t *dispex) +{ + EnumeratorInstance *This; + + This = enumerator_from_jsdisp(dispex); + if (This->array) + jsdisp_release(This->array); + if (This->stringlist) + IDispatch_Release(This->stringlist); + + TRACE("Enumerator_destructor\n"); + + heap_free(dispex); +} + +HRESULT Enumerator_atEnd(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) +{ + EnumeratorInstance *This; + + This = enumerator_from_vdisp(jsthis); + + if (r) + *r = jsval_bool(This->index >= This->length); + + TRACE("Enumerator_atEnd %i %i\n", This->length, This->index); + + return S_OK; +} + +HRESULT Enumerator_item(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) +{ + EnumeratorInstance *This; + + TRACE("Enumerator_item\n"); + + This = enumerator_from_vdisp(jsthis); + + enum_set_item_result(This, r); + + return S_OK; +} + +HRESULT Enumerator_moveFirst(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) +{ + EnumeratorInstance *This; + + TRACE("Enumerator_moveFirst\n"); + + This = enumerator_from_vdisp(jsthis); + This->index = 0; + + enum_set_item_result(This, r); + + return S_OK; +} + +HRESULT Enumerator_moveNext(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) +{ + EnumeratorInstance *This; + + This = enumerator_from_vdisp(jsthis); + + TRACE("Enumerator_moveNext\n"); + + if (This->index < This->length) + This->index++; + + enum_set_item_result(This, r); + + + return S_OK; +} + +static const builtin_prop_t Enumerator_props[] = { + {atEndW, Enumerator_atEnd, PROPF_METHOD}, + {itemW, Enumerator_item, PROPF_METHOD}, + {moveFirstW, Enumerator_moveFirst, PROPF_METHOD}, + {moveNextW, Enumerator_moveNext, PROPF_METHOD}, +}; + +static const builtin_info_t Enumerator_info = { + JSCLASS_OBJECT, + {NULL, NULL, 0}, + ARRAY_SIZE(Enumerator_props), + Enumerator_props, + NULL, + NULL +}; + +static const builtin_info_t EnumeratorInst_info = { + JSCLASS_OBJECT, + {NULL, NULL, 0, NULL}, + 0, + NULL, + Enumerator_destructor, + NULL +}; + +static HRESULT EnumeratorConstr_value(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) +{ + jsdisp_t *obj; + HRESULT hres; + + TRACE("EnumeratorConstr_value\n"); + + switch(flags) { + case DISPATCH_CONSTRUCT: { + if (argc != 1) + return throw_syntax_error(ctx, JS_E_MISSING_ARG, NULL); + + hres = create_enumerator(ctx, &argv[0], &obj); + if(FAILED(hres)) + return hres; + + *r = jsval_obj(obj); + break; + } + default: + FIXME("unimplemented flags: %x\n", flags); + return E_NOTIMPL; + } + + return S_OK; +} + +static HRESULT alloc_enumerator(script_ctx_t *ctx, jsdisp_t *object_prototype, EnumeratorInstance **ret) +{ + EnumeratorInstance *enumerator; + HRESULT hres; + + enumerator = heap_alloc_zero(sizeof(EnumeratorInstance)); + if(!enumerator) + return E_OUTOFMEMORY; + + if(object_prototype) + hres = init_dispex(&enumerator->dispex, ctx, &Enumerator_info, object_prototype); + else + hres = init_dispex_from_constr(&enumerator->dispex, ctx, &EnumeratorInst_info, + ctx->enumerator_constr); + + if(FAILED(hres)) { + heap_free(enumerator); + return hres; + } + + *ret = enumerator; + return S_OK; +} + +static const builtin_info_t EnumeratorConstr_info = { + JSCLASS_FUNCTION, + DEFAULT_FUNCTION_VALUE, + 0, + NULL, + NULL, + NULL +}; + +HRESULT create_enumerator_constr(script_ctx_t *ctx, jsdisp_t *object_prototype, jsdisp_t **ret) +{ + EnumeratorInstance *enumerator; + HRESULT hres; + static const WCHAR EnumeratorW[] = {'E','n','u','m','e','r','a','t','o','r',0}; + + hres = alloc_enumerator(ctx, object_prototype, &enumerator); + if(FAILED(hres)) + return hres; + + hres = create_builtin_constructor(ctx, EnumeratorConstr_value, + EnumeratorW, &EnumeratorConstr_info, + PROPF_CONSTR|1, &enumerator->dispex, ret); + jsdisp_release(&enumerator->dispex); + + return hres; +} + +HRESULT create_enumerator(script_ctx_t *ctx, jsval_t *argv, jsdisp_t **ret) +{ + EnumeratorInstance *enumerator; + HRESULT hres; + IDispatch *dummy; + IDispatch *obj = NULL; + + int jsdatatype = -1; + int jslength = 0; + jsdisp_t *jsarray = NULL; + IDispatch *jsstringlist = NULL; + + if(is_object_instance(*argv)) + { + obj = get_object(*argv); + jsarray = iface_to_jsdisp(obj); + if ((jsarray) && + (is_class(jsarray, JSCLASS_ARRAY))) + { + TRACE("array\n"); + jsdatatype = DATATYPE_ARRAY; + jslength = array_get_length(jsarray); + } + else + { + if (jsarray) + jsdisp_release(jsarray); + /* check if its a stringlist or drivecollection */ + if (SUCCEEDED(IDispatch_QueryInterface(obj, &IID_StringList, (void*)&dummy))) + { + TRACE("Enumerator: stringlist\n"); + jsdatatype = DATATYPE_STRINGLIST; + } + else if (SUCCEEDED(IDispatch_QueryInterface(obj, &IID_IDriveCollection, (void*)&dummy))) + { + TRACE("Enumerator: drivecollection\n"); + jsdatatype = DATATYPE_DRIVECOLLECTION; + } + else + { + FIXME("Enumerator: unexpected type!\n"); + return E_INVALIDARG; + } + + hres = Dispatch_Count(obj, &jslength); + if (FAILED(hres)) + { + ERR("Dispatch_Count failed %d\n", hres); + return -1; + } + TRACE("Count %i\n", jslength); + + jsstringlist = obj; + } + } + else + { + FIXME("type not implemented!\n"); + return E_NOTIMPL; + } + + hres = alloc_enumerator(ctx, NULL, &enumerator); + if(FAILED(hres)) + return hres; + + if (jsstringlist) + IDispatch_AddRef(jsstringlist); + enumerator->index = 0; + enumerator->length = jslength; + enumerator->datatype = jsdatatype; + enumerator->array = jsarray; + enumerator->stringlist = jsstringlist; + + *ret = &enumerator->dispex; + return S_OK; +} diff --git a/dlls/jscript/global.c b/dlls/jscript/global.c index 33de641483..61a756be0e 100644 --- a/dlls/jscript/global.c +++ b/dlls/jscript/global.c @@ -113,13 +113,6 @@ static WCHAR int_to_char(int i) return 'A'+i-10; }
-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, unsigned argc, jsval_t *argv, jsval_t *r) { @@ -942,7 +935,6 @@ static HRESULT JSGlobal_decodeURIComponent(script_ctx_t *ctx, vdisp_t *jsthis, W
static const builtin_prop_t JSGlobal_props[] = { {CollectGarbageW, JSGlobal_CollectGarbage, PROPF_METHOD}, - {EnumeratorW, JSGlobal_Enumerator, PROPF_METHOD|7}, {_GetObjectW, JSGlobal_GetObject, PROPF_METHOD|2}, {ScriptEngineW, JSGlobal_ScriptEngine, PROPF_METHOD}, {ScriptEngineBuildVersionW, JSGlobal_ScriptEngineBuildVersion, PROPF_METHOD}, @@ -1019,6 +1011,16 @@ static HRESULT init_constructors(script_ctx_t *ctx, jsdisp_t *object_prototype) if(FAILED(hres)) return hres;
+ hres = create_enumerator_constr(ctx, object_prototype, &ctx->enumerator_constr); + if(FAILED(hres)) + return hres; + + /* Enumerator is a MS extension */ + hres = jsdisp_define_data_property(ctx->global, EnumeratorW, PROPF_WRITABLE, + jsval_obj(ctx->enumerator_constr)); + if(FAILED(hres)) + return hres; + hres = init_error_constr(ctx, object_prototype); if(FAILED(hres)) return hres; diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h index 2af5b598bd..de539b77b1 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -326,6 +326,7 @@ 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; HRESULT create_json(script_ctx_t*,jsdisp_t**) DECLSPEC_HIDDEN; +HRESULT create_enumerator(script_ctx_t *ctx, jsval_t *argv, jsdisp_t **ret) DECLSPEC_HIDDEN;
typedef enum { NO_HINT, @@ -436,6 +437,7 @@ struct _script_ctx_t { jsdisp_t *array_constr; jsdisp_t *bool_constr; jsdisp_t *date_constr; + jsdisp_t *enumerator_constr; jsdisp_t *error_constr; jsdisp_t *eval_error_constr; jsdisp_t *range_error_constr; @@ -468,6 +470,7 @@ 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_enumerator_constr(script_ctx_t*,jsdisp_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; @@ -590,3 +593,10 @@ static inline void unlock_module(void) { InterlockedDecrement(&module_ref); } + +/* Stringlist_xxx-functions borrowed from wintest (msi) + * FIXME: share it to avoid code duplication ... + */ +/* all these interface have the same item and count-property :-) */ +DEFINE_GUID(IID_StringList, 0x000C1095, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); +DEFINE_GUID(IID_IDriveCollection, 0xc7c3f5a1, 0x88a3, 0x11d0, 0xab, 0xcb, 0x00, 0xa0, 0xc9, 0x0f, 0xff, 0xc0); diff --git a/dlls/jscript/jsglobal.idl b/dlls/jscript/jsglobal.idl index b8604e99f2..7e0c1a30cf 100644 --- a/dlls/jscript/jsglobal.idl +++ b/dlls/jscript/jsglobal.idl @@ -74,9 +74,6 @@ library JSGlobal [id(DISPID_GLOBAL_VBARRAY)] VARIANT VBArray();
- [id(DISPID_GLOBAL_ENUMERATOR)] - VARIANT Enumerator(); - [id(DISPID_GLOBAL_ESCAPE)] VARIANT escape(VARIANT String);
diff --git a/dlls/jscript/tests/rsrc.rc b/dlls/jscript/tests/rsrc.rc index d9ee6b23ae..b130df294a 100644 --- a/dlls/jscript/tests/rsrc.rc +++ b/dlls/jscript/tests/rsrc.rc @@ -25,6 +25,9 @@ cc.js 40 "cc.js" /* @makedep: lang.js */ lang.js 40 "lang.js"
+/* @makedep: extension.js */ +extension.js 40 "extension.js" + /* @makedep: regexp.js */ regexp.js 40 "regexp.js"
diff --git a/dlls/jscript/tests/run.c b/dlls/jscript/tests/run.c index aadb31700d..9e92a418f1 100644 --- a/dlls/jscript/tests/run.c +++ b/dlls/jscript/tests/run.c @@ -2684,6 +2684,7 @@ static BOOL run_tests(void)
run_from_res("lang.js"); run_from_res("api.js"); + run_from_res("extension.js"); run_from_res("regexp.js"); run_from_res("cc.js");
-- 2.11.0
Signed-off-by: Andreas Maier staubim@quantentunnel.de --- dlls/jscript/tests/extension.js | 64 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 dlls/jscript/tests/extension.js
diff --git a/dlls/jscript/tests/extension.js b/dlls/jscript/tests/extension.js new file mode 100644 index 0000000000..92849097e9 --- /dev/null +++ b/dlls/jscript/tests/extension.js @@ -0,0 +1,64 @@ +/* + * Copyright 2019 Andreas Maier + * + * 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 + */ + +var objdata = []; +obj = new Enumerator(objdata); +ok(obj.atEnd(), "atEnd() called before moveFirst should True!"); + + +var objdata = ["A","B"]; +obj = new Enumerator(objdata); +ok(!obj.atEnd(), "atEnd() called before moveFirst should False!"); +ok(obj.item() === objdata[0], + "obj (Enumerator): item (called before moveFirst) value wrong! "+ + "(is " + obj.item() + ", should " + objdata[0] + ")"); +obj.moveFirst(); +for (var i1 = 0; i1 < objdata.length; i1++) +{ + if (obj.atEnd()) + { + ok(false, i1 + ": obj (Enumerator): to less items!"); + break; + } + ok(obj.item() === objdata[i1], + i1 + ": obj (Enumerator): item value wrong! "+ + "(is " + obj.item() + ", should " + objdata[i1] + ")"); + obj.moveNext(); +} +ok(obj.atEnd(), "obj (Enumerator): to much items!"); + +/* +todo_wine_ok(... +-> activate if implemented ... +var objdata = new ActiveXObject("Scripting.FileSystemObject").Drives; +obj = new Enumerator(objdata); +obj.moveFirst(); +for (var i1 = 0; i1 < objdata.Count; i1++) +{ + *//* Strings like "C:", "D:" ... *//* + DriveLetter = obj.item().Path; + ok(DriveLetter.length === 2, + "Expected driver-letter e.g. C:, D:, ... - wrong length "+DriveLetter.length); + ok(DriveLetter.charAt(1) === ":", + "Expected driver-letter e.g. C:, D:, ... - "+DriveLetter); + obj.moveNext(); +} +ok(obj.atEnd(), "obj (Enumerator): to much items!"); +*/ + +reportSuccess(); -- 2.11.0
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=51036
Your paranoid android.
=== debian9 (32 bit report) ===
jscript: run.c:890: Test failed: api.js: L"Enumerator.length = 1" run.c:890: Test failed: api.js: L"Enumerator.length = 1"
=== debian9 (32 bit French report) ===
jscript: run.c:890: Test failed: api.js: L"Enumerator.length = 1" run.c:890: Test failed: api.js: L"Enumerator.length = 1"
=== debian9 (32 bit Japanese:Japan report) ===
jscript: run.c:890: Test failed: api.js: L"Enumerator.length = 1" run.c:890: Test failed: api.js: L"Enumerator.length = 1"
=== debian9 (32 bit Chinese:China report) ===
jscript: run.c:890: Test failed: api.js: L"Enumerator.length = 1" run.c:890: Test failed: api.js: L"Enumerator.length = 1"
=== debian9 (32 bit WoW report) ===
jscript: run.c:890: Test failed: api.js: L"Enumerator.length = 1" run.c:890: Test failed: api.js: L"Enumerator.length = 1"
=== debian9 (64 bit WoW report) ===
jscript: run.c:890: Test failed: api.js: L"Enumerator.length = 1" run.c:890: Test failed: api.js: L"Enumerator.length = 1"
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=51035
Your paranoid android.
=== build (build log) ===
../wine/dlls/jscript/tests/rsrc.rc:28: error: extension.js: No such file or directory config.status: error: could not create Makefile Makefile:1525: recipe for target 'Makefile' failed Task: The exe32 Wine crossbuild failed
=== debian9 (build log) ===
../wine/dlls/jscript/tests/rsrc.rc:28: error: extension.js: No such file or directory config.status: error: could not create Makefile Makefile:1458: recipe for target 'Makefile' failed Task: The win32 build failed
=== debian9 (build log) ===
../wine/dlls/jscript/tests/rsrc.rc:28: error: extension.js: No such file or directory config.status: error: could not create Makefile Makefile:1523: recipe for target 'Makefile' failed Task: The wow64 build failed
Hi Andreas,
Thanks for the patch.
On 4/15/19 9:26 PM, Andreas Maier wrote:
Enumerator is an MS extension. This fixes installatiion of VyChat219.msi.
Signed-off-by: Andreas Maierstaubim@quantentunnel.de
dlls/jscript/Makefile.in | 1 + dlls/jscript/enumerator.c | 455 +++++++++++++++++++++++++++++++++++++++++++++ dlls/jscript/global.c | 18 +- dlls/jscript/jscript.h | 10 + dlls/jscript/jsglobal.idl | 3 - dlls/jscript/tests/rsrc.rc | 3 + dlls/jscript/tests/run.c | 1 + 7 files changed, 480 insertions(+), 11 deletions(-) create mode 100644 dlls/jscript/enumerator.c
Please split the patch. Eg. send a stub implementation first that has only a constructor that creates an instance with its methods returning E_NOTIMPL first, something that would allow a one-line test to pass:
new Enumerator([]);
That part could mostly go as is, I have some comments to object implementations bellow.
+#define DATATYPE_ARRAY 0 +#define DATATYPE_STRINGLIST 1 +#define DATATYPE_DRIVECOLLECTION 2
+typedef struct {
- jsdisp_t dispex;
- int index;
- int length;
- int datatype;
- /* constructor with jsarray e.g. ["A","B"] */
- jsdisp_t *array;
- /* constructor with stringlist-interface
methods Items and Count are available.
e.g. StringList or IDriveCollection-Interface */
- IDispatch *stringlist;
+} EnumeratorInstance;
It doesn't look right to have to implement it for each particular interface. We will likely need separate code path for internal jscript objects and general IDipsatch objects, but we shouldn't need to know anything about IDriveCollection here. This will need more testing. I've attached a tiny first step for such investigation. It uses Enumerator constructor on test-provided object. If you run it on Windows, you will see that it tries to call Invoke(DISPID_NEWENUM) and fails because we don't implement that. My guess would be that it needs DISPID_NEWENUM to succeed and then queries for IEnumVARIANT on the result, but it would need more testing. If my guess is right, we'd need just IEnumVARIANT pointer here.
diff --git a/dlls/jscript/jsglobal.idl b/dlls/jscript/jsglobal.idl index b8604e99f2..7e0c1a30cf 100644 --- a/dlls/jscript/jsglobal.idl +++ b/dlls/jscript/jsglobal.idl @@ -74,9 +74,6 @@ library JSGlobal [id(DISPID_GLOBAL_VBARRAY)] VARIANT VBArray();
[id(DISPID_GLOBAL_ENUMERATOR)]
VARIANT Enumerator();
[id(DISPID_GLOBAL_ESCAPE)] VARIANT escape(VARIANT String);
Why do you remove it?
diff --git a/dlls/jscript/tests/rsrc.rc b/dlls/jscript/tests/rsrc.rc index d9ee6b23ae..b130df294a 100644 --- a/dlls/jscript/tests/rsrc.rc +++ b/dlls/jscript/tests/rsrc.rc @@ -25,6 +25,9 @@ cc.js 40 "cc.js" /* @makedep: lang.js */ lang.js 40 "lang.js"
+/* @makedep: extension.js */ +extension.js 40 "extension.js"
- /* @makedep: regexp.js */ regexp.js 40 "regexp.js"
diff --git a/dlls/jscript/tests/run.c b/dlls/jscript/tests/run.c index aadb31700d..9e92a418f1 100644 --- a/dlls/jscript/tests/run.c +++ b/dlls/jscript/tests/run.c @@ -2684,6 +2684,7 @@ static BOOL run_tests(void)
run_from_res("lang.js"); run_from_res("api.js");
- run_from_res("extension.js");
Please put tests into existing files. For plain JavaScript code, api.js would be appropriate. For test checking interaction with host objects, having short scripts inside run.c will be probably better.
Thanks,
Jacek
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=51057
Your paranoid android.
=== build (build log) ===
error: corrupt patch at line 221 Task: Patch failed to apply
=== debian9 (build log) ===
error: corrupt patch at line 221 Task: Patch failed to apply
=== debian9 (build log) ===
error: corrupt patch at line 221 Task: Patch failed to apply
Enumerator is an MS extension. Its needed to succeed VyChat219.msi installation.
Signed-off-by: Andreas Maier staubim@quantentunnel.de --- dlls/jscript/Makefile.in | 1 + dlls/jscript/enumerator.c | 194 ++++++++++++++++++++++++++++++++++++++++++++++ dlls/jscript/global.c | 9 ++- dlls/jscript/jscript.h | 6 ++ 4 files changed, 208 insertions(+), 2 deletions(-) create mode 100644 dlls/jscript/enumerator.c
diff --git a/dlls/jscript/Makefile.in b/dlls/jscript/Makefile.in index 34ed193742..1cc58a5ed6 100644 --- a/dlls/jscript/Makefile.in +++ b/dlls/jscript/Makefile.in @@ -10,6 +10,7 @@ C_SRCS = \ decode.c \ dispex.c \ engine.c \ + enumerator.c \ error.c \ function.c \ global.c \ diff --git a/dlls/jscript/enumerator.c b/dlls/jscript/enumerator.c new file mode 100644 index 0000000000..9756d219e4 --- /dev/null +++ b/dlls/jscript/enumerator.c @@ -0,0 +1,194 @@ +/* + * Copyright 2019 Andreas Maier + * + * 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 "config.h" +#include "wine/port.h" + +#include <math.h> +#include <assert.h> + +#include "jscript.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(jscript); + +typedef struct { + jsdisp_t dispex; +} EnumeratorInstance; + +static const WCHAR atEndW[] = {'a','t','E','n','d',0}; +static const WCHAR itemW[] = {'i','t','e','m',0}; +static const WCHAR moveFirstW[] = {'m','o','v','e','F','i','r','s','t',0}; +static const WCHAR moveNextW[] = {'m','o','v','e','N','e','x','t',0}; + +static void Enumerator_destructor(jsdisp_t *dispex) +{ + TRACE("Enumerator_destructor\n"); + + heap_free(dispex); +} + +HRESULT Enumerator_atEnd(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) +{ + TRACE("Enumerator_atEnd\n"); + + return E_NOTIMPL; +} + +HRESULT Enumerator_item(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) +{ + TRACE("Enumerator_item\n"); + + return E_NOTIMPL; +} + +HRESULT Enumerator_moveFirst(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) +{ + TRACE("Enumerator_moveFirst\n"); + + return E_NOTIMPL; +} + +HRESULT Enumerator_moveNext(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) +{ + TRACE("Enumerator_moveNext\n"); + + return E_NOTIMPL; +} + +static const builtin_prop_t Enumerator_props[] = { + {atEndW, Enumerator_atEnd, PROPF_METHOD}, + {itemW, Enumerator_item, PROPF_METHOD}, + {moveFirstW, Enumerator_moveFirst, PROPF_METHOD}, + {moveNextW, Enumerator_moveNext, PROPF_METHOD}, +}; + +static const builtin_info_t Enumerator_info = { + JSCLASS_OBJECT, + {NULL, NULL, 0}, + ARRAY_SIZE(Enumerator_props), + Enumerator_props, + NULL, + NULL +}; + +static const builtin_info_t EnumeratorInst_info = { + JSCLASS_OBJECT, + {NULL, NULL, 0, NULL}, + 0, + NULL, + Enumerator_destructor, + NULL +}; + +HRESULT EnumeratorConstr_value(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv, + jsval_t *r) +{ + jsdisp_t *obj; + HRESULT hres; + + TRACE("EnumeratorConstr_value\n"); + + switch(flags) { + case DISPATCH_CONSTRUCT: { + if (argc != 1) + return throw_syntax_error(ctx, JS_E_MISSING_ARG, NULL); + + hres = create_enumerator(ctx, &argv[0], &obj); + if(FAILED(hres)) + return hres; + + *r = jsval_obj(obj); + break; + } + default: + FIXME("unimplemented flags: %x\n", flags); + return E_NOTIMPL; + } + + return S_OK; +} + +static HRESULT alloc_enumerator(script_ctx_t *ctx, jsdisp_t *object_prototype, EnumeratorInstance **ret) +{ + EnumeratorInstance *enumerator; + HRESULT hres; + + enumerator = heap_alloc_zero(sizeof(EnumeratorInstance)); + if(!enumerator) + return E_OUTOFMEMORY; + + if(object_prototype) + hres = init_dispex(&enumerator->dispex, ctx, &Enumerator_info, object_prototype); + else + hres = init_dispex_from_constr(&enumerator->dispex, ctx, &EnumeratorInst_info, + ctx->enumerator_constr); + + if(FAILED(hres)) { + heap_free(enumerator); + return hres; + } + + *ret = enumerator; + return S_OK; +} + +HRESULT create_enumerator(script_ctx_t *ctx, jsval_t *argv, jsdisp_t **ret) +{ + EnumeratorInstance *enumerator; + HRESULT hres; + + hres = alloc_enumerator(ctx, NULL, &enumerator); + if(FAILED(hres)) + return hres; + + *ret = &enumerator->dispex; + return S_OK; +} + +static const builtin_info_t EnumeratorConstr_info = { + JSCLASS_FUNCTION, + DEFAULT_FUNCTION_VALUE, + 0, + NULL, + NULL, + NULL +}; + +HRESULT create_enumerator_constr(script_ctx_t *ctx, jsdisp_t *object_prototype, jsdisp_t **ret) +{ + EnumeratorInstance *enumerator; + HRESULT hres; + static const WCHAR EnumeratorW[] = {'E','n','u','m','e','r','a','t','o','r',0}; + + hres = alloc_enumerator(ctx, object_prototype, &enumerator); + if(FAILED(hres)) + return hres; + + hres = create_builtin_constructor(ctx, EnumeratorConstr_value, + EnumeratorW, &EnumeratorConstr_info, + PROPF_CONSTR|1, &enumerator->dispex, ret); + jsdisp_release(&enumerator->dispex); + + return hres; +} diff --git a/dlls/jscript/global.c b/dlls/jscript/global.c index 33de641483..57cc275efd 100644 --- a/dlls/jscript/global.c +++ b/dlls/jscript/global.c @@ -116,8 +116,9 @@ static WCHAR int_to_char(int i) 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; + TRACE("JSGlobal_Enumerator\n"); + + return EnumeratorConstr_value(ctx, jsthis, flags, argc, argv, r); }
static HRESULT JSGlobal_escape(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, @@ -1019,6 +1020,10 @@ static HRESULT init_constructors(script_ctx_t *ctx, jsdisp_t *object_prototype) if(FAILED(hres)) return hres;
+ hres = create_enumerator_constr(ctx, object_prototype, &ctx->enumerator_constr); + if(FAILED(hres)) + return hres; + hres = init_error_constr(ctx, object_prototype); if(FAILED(hres)) return hres; diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h index 2af5b598bd..a4396a1cd8 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -326,6 +326,7 @@ 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; HRESULT create_json(script_ctx_t*,jsdisp_t**) DECLSPEC_HIDDEN; +HRESULT create_enumerator(script_ctx_t *ctx, jsval_t *argv, jsdisp_t **ret) DECLSPEC_HIDDEN;
typedef enum { NO_HINT, @@ -436,6 +437,7 @@ struct _script_ctx_t { jsdisp_t *array_constr; jsdisp_t *bool_constr; jsdisp_t *date_constr; + jsdisp_t *enumerator_constr; jsdisp_t *error_constr; jsdisp_t *eval_error_constr; jsdisp_t *range_error_constr; @@ -468,12 +470,16 @@ 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_enumerator_constr(script_ctx_t*,jsdisp_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;
+HRESULT EnumeratorConstr_value(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, + unsigned argc, jsval_t *argv, jsval_t *r) DECLSPEC_HIDDEN; + IUnknown *create_ax_site(script_ctx_t*) DECLSPEC_HIDDEN; HRESULT create_jscaller(script_ctx_t*) DECLSPEC_HIDDEN;
-- 2.11.0
Signed-off-by: Andreas Maier staubim@quantentunnel.de --- dlls/jscript/tests/api.js | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/dlls/jscript/tests/api.js b/dlls/jscript/tests/api.js index 38b2e666da..78c0958301 100644 --- a/dlls/jscript/tests/api.js +++ b/dlls/jscript/tests/api.js @@ -58,6 +58,8 @@ testNoEnumerables("Function"); testNoEnumerables("Function.prototype"); testNoEnumerables("testNoEnumerates"); testNoEnumerables("VBArray"); +testNoEnumerables("new Enumerator([])"); +testNoEnumerables("Enumerator([])");
ok(Object.propertyIsEnumerable("prototype") === false, "Object.prototype is enumerable"); ok(Math.propertyIsEnumerable("E") === false, "Math.E is enumerable"); @@ -341,6 +343,8 @@ ok(tmp === "[object Object]", "toString.call(this) = " + tmp); ok(tmp === "[object Object]", "toString.call(arguments) = " + tmp); tmp = Object.prototype.toString.call(new VBArray(createArray())); ok(tmp === "[object Object]", "toString.call(new VBArray()) = " + tmp); +(tmp = new Enumerator([])).f = Object.prototype.toString; +ok(tmp.f() === "[object Object]", "tmp.f() = " + tmp.f());
function TSTestConstr() {} TSTestConstr.prototype = { toString: function() { return "test"; } }; -- 2.11.0
Hi Andreas,
On 4/17/19 10:31 PM, Andreas Maier wrote:
+#include "config.h" +#include "wine/port.h"
+#include <math.h>
Those are not needed, AFAICS.
diff --git a/dlls/jscript/global.c b/dlls/jscript/global.c index 33de641483..57cc275efd 100644 --- a/dlls/jscript/global.c +++ b/dlls/jscript/global.c @@ -116,8 +116,9 @@ static WCHAR int_to_char(int i) 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;
- TRACE("JSGlobal_Enumerator\n");
- return EnumeratorConstr_value(ctx, jsthis, flags, argc, argv, r); }
The way you handled it in v1 was better as it covered more corner cases. Please use jsdisp_define_data_property() in init_constructors() to set the constructor on global object.
Thanks,
Jacek
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=51121
Your paranoid android.
=== debian9 (build log) ===
error: patch failed: dlls/jscript/global.c:116 Task: Patch failed to apply
=== debian9 (build log) ===
error: patch failed: dlls/jscript/global.c:116 Task: Patch failed to apply