Author: akhaldi
Date: Thu Mar 3 13:24:43 2016
New Revision: 70871
URL:
http://svn.reactos.org/svn/reactos?rev=70871&view=rev
Log:
[JSCRIPT] Sync with Wine Staging 1.9.4. CORE-10912
Added:
trunk/reactos/dll/win32/jscript/json.c (with props)
Modified:
trunk/reactos/dll/win32/jscript/CMakeLists.txt
trunk/reactos/dll/win32/jscript/array.c
trunk/reactos/dll/win32/jscript/bool.c
trunk/reactos/dll/win32/jscript/function.c
trunk/reactos/dll/win32/jscript/global.c
trunk/reactos/dll/win32/jscript/jscript.h
trunk/reactos/dll/win32/jscript/jsutils.c
trunk/reactos/dll/win32/jscript/lex.c
trunk/reactos/dll/win32/jscript/number.c
trunk/reactos/dll/win32/jscript/object.c
trunk/reactos/dll/win32/jscript/parser.h
trunk/reactos/media/doc/README.WINE
Modified: trunk/reactos/dll/win32/jscript/CMakeLists.txt
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/jscript/CMakeLis…
==============================================================================
--- trunk/reactos/dll/win32/jscript/CMakeLists.txt [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/jscript/CMakeLists.txt [iso-8859-1] Thu Mar 3 13:24:43 2016
@@ -21,6 +21,7 @@
global.c
jscript.c
jscript_main.c
+ json.c
jsregexp.c
jsstr.c
jsutils.c
Modified: trunk/reactos/dll/win32/jscript/array.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/jscript/array.c?…
==============================================================================
--- trunk/reactos/dll/win32/jscript/array.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/jscript/array.c [iso-8859-1] Thu Mar 3 13:24:43 2016
@@ -55,6 +55,12 @@
return is_vclass(jsthis, JSCLASS_ARRAY) ? array_from_vdisp(jsthis) : NULL;
}
+unsigned array_get_length(jsdisp_t *array)
+{
+ assert(is_class(array, JSCLASS_ARRAY));
+ return array_from_jsdisp(array)->length;
+}
+
static HRESULT get_length(script_ctx_t *ctx, vdisp_t *vdisp, jsdisp_t **jsthis, DWORD
*ret)
{
ArrayInstance *array;
Modified: trunk/reactos/dll/win32/jscript/bool.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/jscript/bool.c?r…
==============================================================================
--- trunk/reactos/dll/win32/jscript/bool.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/jscript/bool.c [iso-8859-1] Thu Mar 3 13:24:43 2016
@@ -33,6 +33,12 @@
return is_vclass(jsthis, JSCLASS_BOOLEAN) ? (BoolInstance*)jsthis->u.jsdisp :
NULL;
}
+BOOL bool_obj_value(jsdisp_t *obj)
+{
+ assert(is_class(obj, JSCLASS_BOOLEAN));
+ return ((BoolInstance*)obj)->val;
+}
+
/* ECMA-262 3rd Edition 15.6.4.2 */
static HRESULT Bool_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned
argc, jsval_t *argv, jsval_t *r)
{
Modified: trunk/reactos/dll/win32/jscript/function.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/jscript/function…
==============================================================================
--- trunk/reactos/dll/win32/jscript/function.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/jscript/function.c [iso-8859-1] Thu Mar 3 13:24:43 2016
@@ -814,6 +814,7 @@
TRACE("\n");
switch(flags) {
+ case DISPATCH_METHOD:
case DISPATCH_CONSTRUCT: {
IDispatch *ret;
Modified: trunk/reactos/dll/win32/jscript/global.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/jscript/global.c…
==============================================================================
--- trunk/reactos/dll/win32/jscript/global.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/jscript/global.c [iso-8859-1] Thu Mar 3 13:24:43 2016
@@ -57,6 +57,7 @@
{'S','c','r','i','p','t','E','n','g','i','n','e','B','u','i','l','d','V','e','r','s','i','o','n',0};
static const WCHAR CollectGarbageW[] =
{'C','o','l','l','e','c','t','G','a','r','b','a','g','e',0};
static const WCHAR MathW[] = {'M','a','t','h',0};
+static const WCHAR JSONW[] = {'J','S','O','N',0};
static const WCHAR encodeURIW[] =
{'e','n','c','o','d','e','U','R','I',0};
static const WCHAR decodeURIW[] =
{'d','e','c','o','d','e','U','R','I',0};
static const WCHAR encodeURIComponentW[] =
{'e','n','c','o','d','e','U','R','I','C','o','m','p','o','n','e','n','t',0};
@@ -254,8 +255,7 @@
if(FAILED(hres))
return hres;
- if(!isinf(n) && !isnan(n))
- ret = TRUE;
+ ret = is_finite(n);
}
if(r)
@@ -1098,6 +1098,19 @@
if(FAILED(hres))
return hres;
+ if(ctx->version >= 2) {
+ jsdisp_t *json;
+
+ hres = create_json(ctx, &json);
+ if(FAILED(hres))
+ return hres;
+
+ hres = jsdisp_propput_dontenum(ctx->global, JSONW, jsval_obj(json));
+ jsdisp_release(json);
+ if(FAILED(hres))
+ return hres;
+ }
+
hres = create_activex_constr(ctx, &constr);
if(FAILED(hres))
return hres;
Modified: trunk/reactos/dll/win32/jscript/jscript.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/jscript/jscript.…
==============================================================================
--- trunk/reactos/dll/win32/jscript/jscript.h [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/jscript/jscript.h [iso-8859-1] Thu Mar 3 13:24:43 2016
@@ -131,7 +131,8 @@
JSCLASS_REGEXP,
JSCLASS_STRING,
JSCLASS_ARGUMENTS,
- JSCLASS_VBARRAY
+ JSCLASS_VBARRAY,
+ JSCLASS_JSON
} jsclass_t;
jsdisp_t *iface_to_jsdisp(IUnknown*) DECLSPEC_HIDDEN;
@@ -331,6 +332,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;
typedef enum {
NO_HINT,
@@ -353,6 +355,7 @@
HRESULT decode_source(WCHAR*) DECLSPEC_HIDDEN;
HRESULT double_to_string(double,jsstr_t**) DECLSPEC_HIDDEN;
+BOOL is_finite(double) DECLSPEC_HIDDEN;
typedef struct named_item_t {
IDispatch *disp;
@@ -471,6 +474,9 @@
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;
+
+BOOL bool_obj_value(jsdisp_t*) DECLSPEC_HIDDEN;
+unsigned array_get_length(jsdisp_t*) DECLSPEC_HIDDEN;
static inline BOOL is_class(jsdisp_t *jsdisp, jsclass_t class)
{
Added: trunk/reactos/dll/win32/jscript/json.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/jscript/json.c?r…
==============================================================================
--- trunk/reactos/dll/win32/jscript/json.c (added)
+++ trunk/reactos/dll/win32/jscript/json.c [iso-8859-1] Thu Mar 3 13:24:43 2016
@@ -0,0 +1,844 @@
+/*
+ * Copyright 2016 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"
+
+static const WCHAR parseW[] =
{'p','a','r','s','e',0};
+static const WCHAR stringifyW[] =
{'s','t','r','i','n','g','i','f','y',0};
+
+static const WCHAR nullW[] = {'n','u','l','l',0};
+static const WCHAR trueW[] = {'t','r','u','e',0};
+static const WCHAR falseW[] =
{'f','a','l','s','e',0};
+
+static const WCHAR toJSONW[] =
{'t','o','J','S','O','N',0};
+
+typedef struct {
+ const WCHAR *ptr;
+ const WCHAR *end;
+ script_ctx_t *ctx;
+} json_parse_ctx_t;
+
+static BOOL is_json_space(WCHAR c)
+{
+ return c == ' ' || c == '\t' || c == '\n' || c ==
'\r';
+}
+
+static WCHAR skip_spaces(json_parse_ctx_t *ctx)
+{
+ while(is_json_space(*ctx->ptr))
+ ctx->ptr++;
+ return *ctx->ptr;
+}
+
+static BOOL is_keyword(json_parse_ctx_t *ctx, const WCHAR *keyword)
+{
+ unsigned i;
+ for(i=0; keyword[i]; i++) {
+ if(!ctx->ptr[i] || keyword[i] != ctx->ptr[i])
+ return FALSE;
+ }
+ if(is_identifier_char(ctx->ptr[i]))
+ return FALSE;
+ ctx->ptr += i;
+ return TRUE;
+}
+
+/* ECMA-262 5.1 Edition 15.12.1.1 */
+static HRESULT parse_json_string(json_parse_ctx_t *ctx, WCHAR **r)
+{
+ const WCHAR *ptr = ++ctx->ptr;
+ size_t len;
+ WCHAR *buf;
+
+ while(*ctx->ptr && *ctx->ptr != '"') {
+ if(*ctx->ptr++ == '\\')
+ ctx->ptr++;
+ }
+ if(!*ctx->ptr) {
+ FIXME("unterminated string\n");
+ return E_FAIL;
+ }
+
+ len = ctx->ptr-ptr;
+ buf = heap_alloc((len+1)*sizeof(WCHAR));
+ if(!buf)
+ return E_OUTOFMEMORY;
+ if(len)
+ memcpy(buf, ptr, len*sizeof(WCHAR));
+ buf[len] = 0;
+
+ if(!unescape(buf)) {
+ FIXME("unescape failed\n");
+ heap_free(buf);
+ return E_FAIL;
+ }
+
+ ctx->ptr++;
+ *r = buf;
+ return S_OK;
+}
+
+/* ECMA-262 5.1 Edition 15.12.1.2 */
+static HRESULT parse_json_value(json_parse_ctx_t *ctx, jsval_t *r)
+{
+ HRESULT hres;
+
+ switch(skip_spaces(ctx)) {
+
+ /* JSONNullLiteral */
+ case 'n':
+ if(!is_keyword(ctx, nullW))
+ break;
+ *r = jsval_null();
+ return S_OK;
+
+ /* JSONBooleanLiteral */
+ case 't':
+ if(!is_keyword(ctx, trueW))
+ break;
+ *r = jsval_bool(TRUE);
+ return S_OK;
+ case 'f':
+ if(!is_keyword(ctx, falseW))
+ break;
+ *r = jsval_bool(FALSE);
+ return S_OK;
+
+ /* JSONObject */
+ case '{': {
+ WCHAR *prop_name;
+ jsdisp_t *obj;
+ jsval_t val;
+
+ hres = create_object(ctx->ctx, NULL, &obj);
+ if(FAILED(hres))
+ return hres;
+
+ ctx->ptr++;
+ if(skip_spaces(ctx) == '}') {
+ ctx->ptr++;
+ *r = jsval_obj(obj);
+ return S_OK;
+ }
+
+ while(1) {
+ if(*ctx->ptr != '"')
+ break;
+ hres = parse_json_string(ctx, &prop_name);
+ if(FAILED(hres))
+ break;
+
+ if(skip_spaces(ctx) != ':') {
+ FIXME("missing ':'\n");
+ heap_free(prop_name);
+ break;
+ }
+
+ ctx->ptr++;
+ hres = parse_json_value(ctx, &val);
+ if(SUCCEEDED(hres)) {
+ hres = jsdisp_propput_name(obj, prop_name, val);
+ jsval_release(val);
+ }
+ heap_free(prop_name);
+ if(FAILED(hres))
+ break;
+
+ if(skip_spaces(ctx) == '}') {
+ ctx->ptr++;
+ *r = jsval_obj(obj);
+ return S_OK;
+ }
+
+ if(*ctx->ptr++ != ',') {
+ FIXME("expected ','\n");
+ break;
+ }
+ skip_spaces(ctx);
+ }
+
+ jsdisp_release(obj);
+ break;
+ }
+
+ /* JSONString */
+ case '"': {
+ WCHAR *string;
+ jsstr_t *str;
+
+ hres = parse_json_string(ctx, &string);
+ if(FAILED(hres))
+ return hres;
+
+ /* FIXME: avoid reallocation */
+ str = jsstr_alloc(string);
+ heap_free(string);
+ if(!str)
+ return E_OUTOFMEMORY;
+
+ *r = jsval_string(str);
+ return S_OK;
+ }
+
+ /* JSONArray */
+ case '[': {
+ jsdisp_t *array;
+ unsigned i = 0;
+ jsval_t val;
+
+ hres = create_array(ctx->ctx, 0, &array);
+ if(FAILED(hres))
+ return hres;
+
+ ctx->ptr++;
+ if(skip_spaces(ctx) == ']') {
+ ctx->ptr++;
+ *r = jsval_obj(array);
+ return S_OK;
+ }
+
+ while(1) {
+ hres = parse_json_value(ctx, &val);
+ if(FAILED(hres))
+ break;
+
+ hres = jsdisp_propput_idx(array, i, val);
+ jsval_release(val);
+ if(FAILED(hres))
+ break;
+
+ if(skip_spaces(ctx) == ']') {
+ ctx->ptr++;
+ *r = jsval_obj(array);
+ return S_OK;
+ }
+
+ if(*ctx->ptr != ',') {
+ FIXME("expected ','\n");
+ break;
+ }
+
+ ctx->ptr++;
+ i++;
+ }
+
+ jsdisp_release(array);
+ break;
+ }
+
+ /* JSONNumber */
+ default: {
+ int sign = 1;
+ double n;
+
+ if(*ctx->ptr == '-') {
+ sign = -1;
+ ctx->ptr++;
+ skip_spaces(ctx);
+ }
+
+ if(!isdigitW(*ctx->ptr))
+ break;
+
+ if(*ctx->ptr == '0') {
+ ctx->ptr++;
+ n = 0;
+ if(is_identifier_char(*ctx->ptr))
+ break;
+ }else {
+ hres = parse_decimal(&ctx->ptr, ctx->end, &n);
+ if(FAILED(hres))
+ return hres;
+ }
+
+ *r = jsval_number(sign*n);
+ return S_OK;
+ }
+ }
+
+ FIXME("Syntax error at %s\n", debugstr_w(ctx->ptr));
+ return E_FAIL;
+}
+
+/* ECMA-262 5.1 Edition 15.12.2 */
+static HRESULT JSON_parse(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc,
jsval_t *argv, jsval_t *r)
+{
+ json_parse_ctx_t parse_ctx;
+ const WCHAR *buf;
+ jsstr_t *str;
+ jsval_t ret;
+ HRESULT hres;
+
+ if(argc != 1) {
+ FIXME("Unsupported args\n");
+ return E_INVALIDARG;
+ }
+
+ hres = to_flat_string(ctx, argv[0], &str, &buf);
+ if(FAILED(hres))
+ return hres;
+
+ TRACE("%s\n", debugstr_w(buf));
+
+ parse_ctx.ptr = buf;
+ parse_ctx.end = buf + jsstr_length(str);
+ parse_ctx.ctx = ctx;
+ hres = parse_json_value(&parse_ctx, &ret);
+ jsstr_release(str);
+ if(FAILED(hres))
+ return hres;
+
+ if(skip_spaces(&parse_ctx)) {
+ FIXME("syntax error\n");
+ jsval_release(ret);
+ return E_FAIL;
+ }
+
+ if(r)
+ *r = ret;
+ else
+ jsval_release(ret);
+ return S_OK;
+}
+
+typedef struct {
+ script_ctx_t *ctx;
+
+ WCHAR *buf;
+ size_t buf_size;
+ size_t buf_len;
+
+ jsdisp_t **stack;
+ size_t stack_top;
+ size_t stack_size;
+
+ WCHAR gap[11]; /* according to the spec, it's no longer than 10 chars */
+} stringify_ctx_t;
+
+static BOOL stringify_push_obj(stringify_ctx_t *ctx, jsdisp_t *obj)
+{
+ if(!ctx->stack_size) {
+ ctx->stack = heap_alloc(4*sizeof(*ctx->stack));
+ if(!ctx->stack)
+ return FALSE;
+ ctx->stack_size = 4;
+ }else if(ctx->stack_top == ctx->stack_size) {
+ jsdisp_t **new_stack;
+
+ new_stack = heap_realloc(ctx->stack,
ctx->stack_size*2*sizeof(*ctx->stack));
+ if(!new_stack)
+ return FALSE;
+ ctx->stack = new_stack;
+ ctx->stack_size *= 2;
+ }
+
+ ctx->stack[ctx->stack_top++] = obj;
+ return TRUE;
+}
+
+static void stringify_pop_obj(stringify_ctx_t *ctx)
+{
+ ctx->stack_top--;
+}
+
+static BOOL is_on_stack(stringify_ctx_t *ctx, jsdisp_t *obj)
+{
+ size_t i = ctx->stack_top;
+ while(i--) {
+ if(ctx->stack[i] == obj)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static BOOL append_string_len(stringify_ctx_t *ctx, const WCHAR *str, size_t len)
+{
+ if(!ctx->buf_size) {
+ ctx->buf = heap_alloc(len*2*sizeof(WCHAR));
+ if(!ctx->buf)
+ return FALSE;
+ ctx->buf_size = len*2;
+ }else if(ctx->buf_len + len > ctx->buf_size) {
+ WCHAR *new_buf;
+ size_t new_size;
+
+ new_size = ctx->buf_size * 2 + len;
+ new_buf = heap_realloc(ctx->buf, new_size*sizeof(WCHAR));
+ if(!new_buf)
+ return FALSE;
+ ctx->buf = new_buf;
+ ctx->buf_size = new_size;
+ }
+
+ if(len)
+ memcpy(ctx->buf + ctx->buf_len, str, len*sizeof(WCHAR));
+ ctx->buf_len += len;
+ return TRUE;
+}
+
+static inline BOOL append_string(stringify_ctx_t *ctx, const WCHAR *str)
+{
+ return append_string_len(ctx, str, strlenW(str));
+}
+
+static inline BOOL append_char(stringify_ctx_t *ctx, WCHAR c)
+{
+ return append_string_len(ctx, &c, 1);
+}
+
+static inline BOOL append_simple_quote(stringify_ctx_t *ctx, WCHAR c)
+{
+ WCHAR str[] = {'\\',c};
+ return append_string_len(ctx, str, 2);
+}
+
+static HRESULT maybe_to_primitive(script_ctx_t *ctx, jsval_t val, jsval_t *r)
+{
+ jsdisp_t *obj;
+ HRESULT hres;
+
+ if(!is_object_instance(val) || !get_object(val) || !(obj =
iface_to_jsdisp((IUnknown*)get_object(val))))
+ return jsval_copy(val, r);
+
+ if(is_class(obj, JSCLASS_NUMBER)) {
+ double n;
+ hres = to_number(ctx, val, &n);
+ jsdisp_release(obj);
+ if(SUCCEEDED(hres))
+ *r = jsval_number(n);
+ return hres;
+ }
+
+ if(is_class(obj, JSCLASS_STRING)) {
+ jsstr_t *str;
+ hres = to_string(ctx, val, &str);
+ jsdisp_release(obj);
+ if(SUCCEEDED(hres))
+ *r = jsval_string(str);
+ return hres;
+ }
+
+ if(is_class(obj, JSCLASS_BOOLEAN)) {
+ *r = jsval_bool(bool_obj_value(obj));
+ jsdisp_release(obj);
+ return S_OK;
+ }
+
+ *r = jsval_obj(obj);
+ return S_OK;
+}
+
+/* ECMA-262 5.1 Edition 15.12.3 (abstract operation Quote) */
+static HRESULT json_quote(stringify_ctx_t *ctx, const WCHAR *ptr, size_t len)
+{
+ if(!ptr || !append_char(ctx, '"'))
+ return E_OUTOFMEMORY;
+
+ while(len--) {
+ switch(*ptr) {
+ case '"':
+ case '\\':
+ if(!append_simple_quote(ctx, *ptr))
+ return E_OUTOFMEMORY;
+ break;
+ case '\b':
+ if(!append_simple_quote(ctx, 'b'))
+ return E_OUTOFMEMORY;
+ break;
+ case '\f':
+ if(!append_simple_quote(ctx, 'f'))
+ return E_OUTOFMEMORY;
+ break;
+ case '\n':
+ if(!append_simple_quote(ctx, 'n'))
+ return E_OUTOFMEMORY;
+ break;
+ case '\r':
+ if(!append_simple_quote(ctx, 'r'))
+ return E_OUTOFMEMORY;
+ break;
+ case '\t':
+ if(!append_simple_quote(ctx, 't'))
+ return E_OUTOFMEMORY;
+ break;
+ default:
+ if(*ptr < ' ') {
+ const WCHAR formatW[] =
{'\\','u','%','0','4','x',0};
+ WCHAR buf[7];
+ sprintfW(buf, formatW, *ptr);
+ if(!append_string(ctx, buf))
+ return E_OUTOFMEMORY;
+ }else {
+ if(!append_char(ctx, *ptr))
+ return E_OUTOFMEMORY;
+ }
+ }
+ ptr++;
+ }
+
+ return append_char(ctx, '"') ? S_OK : E_OUTOFMEMORY;
+}
+
+static inline BOOL is_callable(jsdisp_t *obj)
+{
+ return is_class(obj, JSCLASS_FUNCTION);
+}
+
+static HRESULT stringify(stringify_ctx_t *ctx, jsval_t val);
+
+/* ECMA-262 5.1 Edition 15.12.3 (abstract operation JA) */
+static HRESULT stringify_array(stringify_ctx_t *ctx, jsdisp_t *obj)
+{
+ unsigned length, i, j;
+ jsval_t val;
+ HRESULT hres;
+
+ if(is_on_stack(ctx, obj)) {
+ FIXME("Found a cycle\n");
+ return E_FAIL;
+ }
+
+ if(!stringify_push_obj(ctx, obj))
+ return E_OUTOFMEMORY;
+
+ if(!append_char(ctx, '['))
+ return E_OUTOFMEMORY;
+
+ length = array_get_length(obj);
+
+ for(i=0; i < length; i++) {
+ if(i && !append_char(ctx, ','))
+ return E_OUTOFMEMORY;
+
+ if(*ctx->gap) {
+ if(!append_char(ctx, '\n'))
+ return E_OUTOFMEMORY;
+
+ for(j=0; j < ctx->stack_top; j++) {
+ if(!append_string(ctx, ctx->gap))
+ return E_OUTOFMEMORY;
+ }
+ }
+
+ hres = jsdisp_get_idx(obj, i, &val);
+ if(FAILED(hres))
+ return hres;
+
+ hres = stringify(ctx, val);
+ if(FAILED(hres))
+ return hres;
+
+ if(hres == S_FALSE && !append_string(ctx, nullW))
+ return E_OUTOFMEMORY;
+ }
+
+ if((length && *ctx->gap && !append_char(ctx, '\n')) ||
!append_char(ctx, ']'))
+ return E_OUTOFMEMORY;
+
+ stringify_pop_obj(ctx);
+ return S_OK;
+}
+
+/* ECMA-262 5.1 Edition 15.12.3 (abstract operation JO) */
+static HRESULT stringify_object(stringify_ctx_t *ctx, jsdisp_t *obj)
+{
+ DISPID dispid = DISPID_STARTENUM;
+ jsval_t val = jsval_undefined();
+ unsigned prop_cnt = 0, i;
+ size_t stepback;
+ BSTR prop_name;
+ HRESULT hres;
+
+ if(is_on_stack(ctx, obj)) {
+ FIXME("Found a cycle\n");
+ return E_FAIL;
+ }
+
+ if(!stringify_push_obj(ctx, obj))
+ return E_OUTOFMEMORY;
+
+ if(!append_char(ctx, '{'))
+ return E_OUTOFMEMORY;
+
+ while((hres = IDispatchEx_GetNextDispID(&obj->IDispatchEx_iface,
fdexEnumDefault, dispid, &dispid)) == S_OK) {
+ jsval_release(val);
+ hres = jsdisp_propget(obj, dispid, &val);
+ if(FAILED(hres))
+ return hres;
+
+ if(is_undefined(val))
+ continue;
+
+ stepback = ctx->buf_len;
+
+ if(prop_cnt && !append_char(ctx, ',')) {
+ hres = E_OUTOFMEMORY;
+ break;
+ }
+
+ if(*ctx->gap) {
+ if(!append_char(ctx, '\n')) {
+ hres = E_OUTOFMEMORY;
+ break;
+ }
+
+ for(i=0; i < ctx->stack_top; i++) {
+ if(!append_string(ctx, ctx->gap)) {
+ hres = E_OUTOFMEMORY;
+ break;
+ }
+ }
+ }
+
+ hres = IDispatchEx_GetMemberName(&obj->IDispatchEx_iface, dispid,
&prop_name);
+ if(FAILED(hres))
+ break;
+
+ hres = json_quote(ctx, prop_name, SysStringLen(prop_name));
+ SysFreeString(prop_name);
+ if(FAILED(hres))
+ break;
+
+ if(!append_char(ctx, ':') || (*ctx->gap && !append_char(ctx,
' '))) {
+ hres = E_OUTOFMEMORY;
+ break;
+ }
+
+ hres = stringify(ctx, val);
+ if(FAILED(hres))
+ break;
+
+ if(hres == S_FALSE) {
+ ctx->buf_len = stepback;
+ continue;
+ }
+
+ prop_cnt++;
+ }
+ jsval_release(val);
+ if(FAILED(hres))
+ return hres;
+
+ if(prop_cnt && *ctx->gap) {
+ if(!append_char(ctx, '\n'))
+ return E_OUTOFMEMORY;
+
+ for(i=1; i < ctx->stack_top; i++) {
+ if(!append_string(ctx, ctx->gap)) {
+ hres = E_OUTOFMEMORY;
+ break;
+ }
+ }
+ }
+
+ if(!append_char(ctx, '}'))
+ return E_OUTOFMEMORY;
+
+ stringify_pop_obj(ctx);
+ return S_OK;
+}
+
+/* ECMA-262 5.1 Edition 15.12.3 (abstract operation Str) */
+static HRESULT stringify(stringify_ctx_t *ctx, jsval_t val)
+{
+ jsval_t value;
+ HRESULT hres;
+
+ if(is_object_instance(val) && get_object(val)) {
+ jsdisp_t *obj;
+ DISPID id;
+
+ obj = iface_to_jsdisp((IUnknown*)get_object(val));
+ if(!obj)
+ return S_FALSE;
+
+ hres = jsdisp_get_id(obj, toJSONW, 0, &id);
+ jsdisp_release(obj);
+ if(hres == S_OK)
+ FIXME("Use toJSON.\n");
+ }
+
+ /* FIXME: Support replacer replacer. */
+
+ hres = maybe_to_primitive(ctx->ctx, val, &value);
+ if(FAILED(hres))
+ return hres;
+
+ switch(jsval_type(value)) {
+ case JSV_NULL:
+ if(!append_string(ctx, nullW))
+ hres = E_OUTOFMEMORY;
+ break;
+ case JSV_BOOL:
+ if(!append_string(ctx, get_bool(value) ? trueW : falseW))
+ hres = E_OUTOFMEMORY;
+ break;
+ case JSV_STRING: {
+ jsstr_t *str = get_string(value);
+ const WCHAR *ptr = jsstr_flatten(str);
+ if(ptr)
+ hres = json_quote(ctx, ptr, jsstr_length(str));
+ else
+ hres = E_OUTOFMEMORY;
+ break;
+ }
+ case JSV_NUMBER: {
+ double n = get_number(value);
+ if(is_finite(n)) {
+ const WCHAR *ptr;
+ jsstr_t *str;
+
+ /* FIXME: Optimize. There is no need for jsstr_t here. */
+ hres = double_to_string(n, &str);
+ if(FAILED(hres))
+ break;
+
+ ptr = jsstr_flatten(str);
+ assert(ptr != NULL);
+ hres = ptr && !append_string_len(ctx, ptr, jsstr_length(str)) ?
E_OUTOFMEMORY : S_OK;
+ jsstr_release(str);
+ }else {
+ if(!append_string(ctx, nullW))
+ hres = E_OUTOFMEMORY;
+ }
+ break;
+ }
+ case JSV_OBJECT: {
+ jsdisp_t *obj;
+
+ obj = iface_to_jsdisp((IUnknown*)get_object(value));
+ if(!obj) {
+ hres = S_FALSE;
+ break;
+ }
+
+ if(!is_callable(obj))
+ hres = is_class(obj, JSCLASS_ARRAY) ? stringify_array(ctx, obj) :
stringify_object(ctx, obj);
+ else
+ hres = S_FALSE;
+
+ jsdisp_release(obj);
+ break;
+ }
+ case JSV_UNDEFINED:
+ hres = S_FALSE;
+ break;
+ case JSV_VARIANT:
+ FIXME("VARIANT\n");
+ hres = E_NOTIMPL;
+ break;
+ }
+
+ jsval_release(value);
+ return hres;
+}
+
+/* ECMA-262 5.1 Edition 15.12.3 */
+static HRESULT JSON_stringify(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned
argc, jsval_t *argv, jsval_t *r)
+{
+ stringify_ctx_t stringify_ctx = {ctx, NULL,0,0, NULL,0,0, {0}};
+ HRESULT hres;
+
+ TRACE("\n");
+
+ if(argc >= 2 && is_object_instance(argv[1])) {
+ FIXME("Replacer %s not yet supported\n", debugstr_jsval(argv[1]));
+ return E_NOTIMPL;
+ }
+
+ if(argc >= 3) {
+ jsval_t space_val;
+
+ hres = maybe_to_primitive(ctx, argv[2], &space_val);
+ if(FAILED(hres))
+ return hres;
+
+ if(is_number(space_val)) {
+ double n = get_number(space_val);
+ if(n >= 1) {
+ int i, len;
+ if(n > 10)
+ n = 10;
+ len = floor(n);
+ for(i=0; i < len; i++)
+ stringify_ctx.gap[i] = ' ';
+ stringify_ctx.gap[len] = 0;
+ }
+ }else if(is_string(space_val)) {
+ jsstr_t *space_str = get_string(space_val);
+ size_t len = jsstr_length(space_str);
+ if(len > 10)
+ len = 10;
+ jsstr_extract(space_str, 0, len, stringify_ctx.gap);
+ }
+
+ jsval_release(space_val);
+ }
+
+ hres = stringify(&stringify_ctx, argv[0]);
+ if(SUCCEEDED(hres) && r) {
+ assert(!stringify_ctx.stack_top);
+
+ if(hres == S_OK) {
+ jsstr_t *ret = jsstr_alloc_len(stringify_ctx.buf, stringify_ctx.buf_len);
+ if(ret)
+ *r = jsval_string(ret);
+ else
+ hres = E_OUTOFMEMORY;
+ }else {
+ *r = jsval_undefined();
+ }
+ }
+
+ heap_free(stringify_ctx.buf);
+ heap_free(stringify_ctx.stack);
+ return hres;
+}
+
+static const builtin_prop_t JSON_props[] = {
+ {parseW, JSON_parse, PROPF_METHOD|2},
+ {stringifyW, JSON_stringify, PROPF_METHOD|3}
+};
+
+static const builtin_info_t JSON_info = {
+ JSCLASS_JSON,
+ {NULL, NULL, 0},
+ sizeof(JSON_props)/sizeof(*JSON_props),
+ JSON_props,
+ NULL,
+ NULL
+};
+
+HRESULT create_json(script_ctx_t *ctx, jsdisp_t **ret)
+{
+ jsdisp_t *json;
+ HRESULT hres;
+
+ json = heap_alloc_zero(sizeof(*json));
+ if(!json)
+ return E_OUTOFMEMORY;
+
+ hres = init_dispex_from_constr(json, ctx, &JSON_info, ctx->object_constr);
+ if(FAILED(hres)) {
+ heap_free(json);
+ return hres;
+ }
+
+ *ret = json;
+ return S_OK;
+}
Propchange: trunk/reactos/dll/win32/jscript/json.c
------------------------------------------------------------------------------
svn:eol-style = native
Modified: trunk/reactos/dll/win32/jscript/jsutils.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/jscript/jsutils.…
==============================================================================
--- trunk/reactos/dll/win32/jscript/jsutils.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/jscript/jsutils.c [iso-8859-1] Thu Mar 3 13:24:43 2016
@@ -43,6 +43,11 @@
return NULL;
}
+BOOL is_finite(double n)
+{
+ return !isnan(n) && !isinf(n);
+}
+
#define MIN_BLOCK_SIZE 128
#define ARENA_FREE_FILLER 0xaa
@@ -631,7 +636,7 @@
if(FAILED(hres))
return hres;
- *ret = isnan(n) || isinf(n) ? 0 : n;
+ *ret = is_finite(n) ? n : 0;
return S_OK;
}
Modified: trunk/reactos/dll/win32/jscript/lex.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/jscript/lex.c?re…
==============================================================================
--- trunk/reactos/dll/win32/jscript/lex.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/jscript/lex.c [iso-8859-1] Thu Mar 3 13:24:43 2016
@@ -19,8 +19,6 @@
#include "jscript.h"
#include "parser.tab.h"
-
-#define LONGLONG_MAX (((LONGLONG)0x7fffffff<<32)|0xffffffff)
static const WCHAR breakW[] =
{'b','r','e','a','k',0};
static const WCHAR caseW[] = {'c','a','s','e',0};
@@ -97,7 +95,7 @@
}
/* ECMA-262 3rd Edition 7.6 */
-static BOOL is_identifier_char(WCHAR c)
+BOOL is_identifier_char(WCHAR c)
{
return isalnumW(c) || c == '$' || c == '_' || c == '\\';
}
@@ -237,7 +235,7 @@
return ctx->ptr != ctx->end;
}
-static BOOL unescape(WCHAR *str)
+BOOL unescape(WCHAR *str)
{
WCHAR *pd, *p, c;
int i;
@@ -394,14 +392,14 @@
return ret;
}
-static BOOL parse_double_literal(parser_ctx_t *ctx, LONG int_part, double *ret)
-{
- LONGLONG d, hlp;
+HRESULT parse_decimal(const WCHAR **iter, const WCHAR *end, double *ret)
+{
+ const WCHAR *ptr = *iter;
+ LONGLONG d = 0, hlp;
int exp = 0;
- d = int_part;
- while(ctx->ptr < ctx->end && isdigitW(*ctx->ptr)) {
- hlp = d*10 + *(ctx->ptr++) - '0';
+ while(ptr < end && isdigitW(*ptr)) {
+ hlp = d*10 + *(ptr++) - '0';
if(d>MAXLONGLONG/10 || hlp<0) {
exp++;
break;
@@ -409,51 +407,48 @@
else
d = hlp;
}
- while(ctx->ptr < ctx->end && isdigitW(*ctx->ptr)) {
+ while(ptr < end && isdigitW(*ptr)) {
exp++;
- ctx->ptr++;
- }
-
- if(*ctx->ptr == '.') {
- ctx->ptr++;
-
- while(ctx->ptr < ctx->end && isdigitW(*ctx->ptr)) {
- hlp = d*10 + *(ctx->ptr++) - '0';
+ ptr++;
+ }
+
+ if(*ptr == '.') {
+ ptr++;
+
+ while(ptr < end && isdigitW(*ptr)) {
+ hlp = d*10 + *(ptr++) - '0';
if(d>MAXLONGLONG/10 || hlp<0)
break;
d = hlp;
exp--;
}
- while(ctx->ptr < ctx->end && isdigitW(*ctx->ptr))
- ctx->ptr++;
- }
-
- if(ctx->ptr < ctx->end && (*ctx->ptr == 'e' ||
*ctx->ptr == 'E')) {
+ while(ptr < end && isdigitW(*ptr))
+ ptr++;
+ }
+
+ if(ptr < end && (*ptr == 'e' || *ptr == 'E')) {
int sign = 1, e = 0;
- ctx->ptr++;
- if(ctx->ptr < ctx->end) {
- if(*ctx->ptr == '+') {
- ctx->ptr++;
- }else if(*ctx->ptr == '-') {
+ if(++ptr < end) {
+ if(*ptr == '+') {
+ ptr++;
+ }else if(*ptr == '-') {
sign = -1;
- ctx->ptr++;
- }else if(!isdigitW(*ctx->ptr)) {
+ ptr++;
+ }else if(!isdigitW(*ptr)) {
WARN("Expected exponent part\n");
- lex_error(ctx, E_FAIL);
- return FALSE;
- }
- }
-
- if(ctx->ptr == ctx->end) {
+ return E_FAIL;
+ }
+ }
+
+ if(ptr == end) {
WARN("unexpected end of file\n");
- lex_error(ctx, E_FAIL);
- return FALSE;
- }
-
- while(ctx->ptr < ctx->end && isdigitW(*ctx->ptr)) {
- if(e > INT_MAX/10 || (e = e*10 + *ctx->ptr++ - '0')<0)
+ return E_FAIL;
+ }
+
+ while(ptr < end && isdigitW(*ptr)) {
+ if(e > INT_MAX/10 || (e = e*10 + *ptr++ - '0')<0)
e = INT_MAX;
}
e *= sign;
@@ -463,22 +458,25 @@
else exp += e;
}
- if(is_identifier_char(*ctx->ptr)) {
+ if(is_identifier_char(*ptr)) {
WARN("wrong char after zero\n");
- lex_error(ctx, JS_E_MISSING_SEMICOLON);
- return FALSE;
+ return JS_E_MISSING_SEMICOLON;
}
*ret = exp>=0 ? d*pow(10, exp) : d/pow(10, -exp);
- return TRUE;
+ *iter = ptr;
+ return S_OK;
}
static BOOL parse_numeric_literal(parser_ctx_t *ctx, double *ret)
{
- LONG l, d;
-
- l = *ctx->ptr++ - '0';
- if(!l) {
+ HRESULT hres;
+
+ if(*ctx->ptr == '0') {
+ LONG d, l = 0;
+
+ ctx->ptr++;
+
if(*ctx->ptr == 'x' || *ctx->ptr == 'X') {
if(++ctx->ptr == ctx->end) {
ERR("unexpected end of file\n");
@@ -534,7 +532,13 @@
}
}
- return parse_double_literal(ctx, l, ret);
+ hres = parse_decimal(&ctx->ptr, ctx->end, ret);
+ if(FAILED(hres)) {
+ lex_error(ctx, hres);
+ return FALSE;
+ }
+
+ return TRUE;
}
static int next_token(parser_ctx_t *ctx, void *lval)
@@ -587,8 +591,12 @@
case '.':
if(++ctx->ptr < ctx->end && isdigitW(*ctx->ptr)) {
double n;
- if(!parse_double_literal(ctx, 0, &n))
+ HRESULT hres;
+ hres = parse_decimal(&ctx->ptr, ctx->end, &n);
+ if(FAILED(hres)) {
+ lex_error(ctx, hres);
return -1;
+ }
*(literal_t**)lval = new_double_literal(ctx, n);
return tNumericLiteral;
}
Modified: trunk/reactos/dll/win32/jscript/number.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/jscript/number.c…
==============================================================================
--- trunk/reactos/dll/win32/jscript/number.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/jscript/number.c [iso-8859-1] Thu Mar 3 13:24:43 2016
@@ -247,7 +247,7 @@
val = number->value;
- if(radix==10 || isnan(val) || isinf(val)) {
+ if(radix==10 || !is_finite(val)) {
hres = to_string(ctx, jsval_number(val), &str);
if(FAILED(hres))
return hres;
@@ -373,7 +373,7 @@
}
val = number->value;
- if(isinf(val) || isnan(val)) {
+ if(!is_finite(val)) {
hres = to_string(ctx, jsval_number(val), &str);
if(FAILED(hres))
return hres;
@@ -414,7 +414,7 @@
}
val = number->value;
- if(isinf(val) || isnan(val)) {
+ if(!is_finite(val)) {
hres = to_string(ctx, jsval_number(val), &str);
if(FAILED(hres))
return hres;
@@ -455,7 +455,7 @@
}
val = number->value;
- if(isinf(val) || isnan(val) || !prec) {
+ if(!is_finite(val) || !prec) {
hres = to_string(ctx, jsval_number(val), &str);
if(FAILED(hres))
return hres;
Modified: trunk/reactos/dll/win32/jscript/object.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/jscript/object.c…
==============================================================================
--- trunk/reactos/dll/win32/jscript/object.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/jscript/object.c [iso-8859-1] Thu Mar 3 13:24:43 2016
@@ -48,7 +48,7 @@
static const WCHAR stringW[] =
{'S','t','r','i','n','g',0};
/* Keep in sync with jsclass_t enum */
static const WCHAR *names[] = {NULL, arrayW, booleanW, dateW, errorW,
- functionW, NULL, mathW, numberW, objectW, regexpW, stringW, objectW, objectW};
+ functionW, NULL, mathW, numberW, objectW, regexpW, stringW, objectW, objectW,
objectW};
TRACE("\n");
Modified: trunk/reactos/dll/win32/jscript/parser.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/jscript/parser.h…
==============================================================================
--- trunk/reactos/dll/win32/jscript/parser.h [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/jscript/parser.h [iso-8859-1] Thu Mar 3 13:24:43 2016
@@ -63,6 +63,10 @@
{
return heap_pool_alloc(&ctx->script->tmp_heap, size);
}
+
+BOOL is_identifier_char(WCHAR) DECLSPEC_HIDDEN;
+BOOL unescape(WCHAR*) DECLSPEC_HIDDEN;
+HRESULT parse_decimal(const WCHAR**,const WCHAR*,double*) DECLSPEC_HIDDEN;
typedef enum {
LT_DOUBLE,
Modified: trunk/reactos/media/doc/README.WINE
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/media/doc/README.WINE?rev=…
==============================================================================
--- trunk/reactos/media/doc/README.WINE [iso-8859-1] (original)
+++ trunk/reactos/media/doc/README.WINE [iso-8859-1] Thu Mar 3 13:24:43 2016
@@ -85,7 +85,7 @@
reactos/dll/win32/iphlpapi # Out of sync
reactos/dll/win32/itircl # Synced to WineStaging-1.7.55
reactos/dll/win32/itss # Synced to WineStaging-1.7.55
-reactos/dll/win32/jscript # Synced to WineStaging-1.7.55
+reactos/dll/win32/jscript # Synced to WineStaging-1.9.4
reactos/dll/win32/jsproxy # Synced to WineStaging-1.7.55
reactos/dll/win32/loadperf # Synced to WineStaging-1.7.55
reactos/dll/win32/localspl # Synced to WineStaging-1.7.55