1 /* 2 * Copyright 2012 Jacek Caban for CodeWeavers 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2.1 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with this library; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 17 */ 18 19 #ifndef JSVAL_H 20 #define JSVAL_H 21 22 #include "jsstr.h" 23 24 /* 25 * jsval_t structure is used to represent JavaScript dynamically-typed values. 26 * It's a (type,value) pair, usually represented as a structure of enum (type) 27 * and union (value of given type). For both memory and speed performance, we 28 * use tricks allowing storing both values as a struct with size equal to 29 * size of double (that is 64-bit) on 32-bit systems. For that, we use the fact 30 * that NaN value representation has 52 (almost) free bits. 31 */ 32 33 #ifdef __i386__ 34 #define JSVAL_DOUBLE_LAYOUT_PTR32 35 #endif 36 37 #ifdef JSVAL_DOUBLE_LAYOUT_PTR32 38 /* NaN exponent and our 0x80000 marker */ 39 #define JSV_VAL(x) (0x7ff80000|x) 40 #else 41 #define JSV_VAL(x) x 42 #endif 43 44 typedef enum { 45 JSV_UNDEFINED = JSV_VAL(1), 46 JSV_NULL = JSV_VAL(2), 47 JSV_OBJECT = JSV_VAL(3), 48 JSV_STRING = JSV_VAL(4), 49 JSV_NUMBER = JSV_VAL(5), 50 JSV_BOOL = JSV_VAL(6), 51 JSV_VARIANT = JSV_VAL(7) 52 } jsval_type_t; 53 54 struct _jsval_t { 55 #ifdef JSVAL_DOUBLE_LAYOUT_PTR32 56 union { 57 double n; 58 struct { 59 union { 60 IDispatch *obj; 61 jsstr_t *str; 62 BOOL b; 63 VARIANT *v; 64 UINT_PTR as_uintptr; 65 } u; 66 jsval_type_t tag; 67 } s; 68 } u; 69 #else 70 jsval_type_t type; 71 union { 72 IDispatch *obj; 73 jsstr_t *str; 74 double n; 75 BOOL b; 76 VARIANT *v; 77 } u; 78 #endif 79 }; 80 81 #ifdef JSVAL_DOUBLE_LAYOUT_PTR32 82 83 C_ASSERT(sizeof(jsval_t) == sizeof(double)); 84 85 #define __JSVAL_TYPE(x) ((x).u.s.tag) 86 #define __JSVAL_BOOL(x) ((x).u.s.u.b) 87 #define __JSVAL_STR(x) ((x).u.s.u.str) 88 #define __JSVAL_OBJ(x) ((x).u.s.u.obj) 89 #define __JSVAL_VAR(x) ((x).u.s.u.v) 90 91 #else 92 93 #define __JSVAL_TYPE(x) ((x).type) 94 #define __JSVAL_BOOL(x) ((x).u.b) 95 #define __JSVAL_STR(x) ((x).u.str) 96 #define __JSVAL_OBJ(x) ((x).u.obj) 97 #define __JSVAL_VAR(x) ((x).u.v) 98 99 #endif 100 101 static inline jsval_t jsval_bool(BOOL b) 102 { 103 jsval_t ret; 104 __JSVAL_TYPE(ret) = JSV_BOOL; 105 __JSVAL_BOOL(ret) = b; 106 return ret; 107 } 108 109 static inline jsval_t jsval_string(jsstr_t *str) 110 { 111 jsval_t ret; 112 __JSVAL_TYPE(ret) = JSV_STRING; 113 __JSVAL_STR(ret) = str; 114 return ret; 115 } 116 117 static inline jsval_t jsval_disp(IDispatch *obj) 118 { 119 jsval_t ret; 120 __JSVAL_TYPE(ret) = JSV_OBJECT; 121 __JSVAL_OBJ(ret) = obj; 122 return ret; 123 } 124 125 static inline jsval_t jsval_obj(jsdisp_t *obj) 126 { 127 return jsval_disp(to_disp(obj)); 128 } 129 130 static inline jsval_t jsval_null(void) 131 { 132 jsval_t ret; 133 __JSVAL_TYPE(ret) = JSV_NULL; 134 return ret; 135 } 136 137 static inline jsval_t jsval_undefined(void) 138 { 139 jsval_t ret; 140 __JSVAL_TYPE(ret) = JSV_UNDEFINED; 141 return ret; 142 } 143 144 static inline jsval_t jsval_number(double n) 145 { 146 jsval_t ret; 147 #ifdef JSVAL_DOUBLE_LAYOUT_PTR32 148 ret.u.n = n; 149 /* normalize NaN value */ 150 if((ret.u.s.tag & 0x7ff00000) == 0x7ff00000) { 151 /* isinf */ 152 if(ret.u.s.tag & 0xfffff) { 153 ret.u.s.tag = 0x7ff00000; 154 ret.u.s.u.as_uintptr = ~0; 155 }else if(ret.u.s.u.as_uintptr) { 156 ret.u.s.tag = 0x7ff00000; 157 } 158 } 159 #else 160 ret.type = JSV_NUMBER; 161 ret.u.n = n; 162 #endif 163 return ret; 164 } 165 166 static inline BOOL is_object_instance(jsval_t v) 167 { 168 return __JSVAL_TYPE(v) == JSV_OBJECT; 169 } 170 171 static inline BOOL is_undefined(jsval_t v) 172 { 173 return __JSVAL_TYPE(v) == JSV_UNDEFINED; 174 } 175 176 static inline BOOL is_null(jsval_t v) 177 { 178 return __JSVAL_TYPE(v) == JSV_NULL; 179 } 180 181 static inline BOOL is_null_instance(jsval_t v) 182 { 183 return is_null(v) || (is_object_instance(v) && !__JSVAL_OBJ(v)); 184 } 185 186 static inline BOOL is_string(jsval_t v) 187 { 188 return __JSVAL_TYPE(v) == JSV_STRING; 189 } 190 191 static inline BOOL is_number(jsval_t v) 192 { 193 #ifdef JSVAL_DOUBLE_LAYOUT_PTR32 194 return (v.u.s.tag & 0x7ff80000) != 0x7ff80000; 195 #else 196 return v.type == JSV_NUMBER; 197 #endif 198 } 199 200 static inline BOOL is_variant(jsval_t v) 201 { 202 return __JSVAL_TYPE(v) == JSV_VARIANT; 203 } 204 205 static inline BOOL is_bool(jsval_t v) 206 { 207 return __JSVAL_TYPE(v) == JSV_BOOL; 208 } 209 210 static inline jsval_type_t jsval_type(jsval_t v) 211 { 212 #ifdef JSVAL_DOUBLE_LAYOUT_PTR32 213 return is_number(v) ? JSV_NUMBER : v.u.s.tag; 214 #else 215 return v.type; 216 #endif 217 } 218 219 static inline IDispatch *get_object(jsval_t v) 220 { 221 return __JSVAL_OBJ(v); 222 } 223 224 static inline double get_number(jsval_t v) 225 { 226 return v.u.n; 227 } 228 229 static inline jsstr_t *get_string(jsval_t v) 230 { 231 return __JSVAL_STR(v); 232 } 233 234 static inline VARIANT *get_variant(jsval_t v) 235 { 236 return __JSVAL_VAR(v); 237 } 238 239 static inline BOOL get_bool(jsval_t v) 240 { 241 return __JSVAL_BOOL(v); 242 } 243 244 HRESULT variant_to_jsval(VARIANT*,jsval_t*) DECLSPEC_HIDDEN; 245 HRESULT jsval_to_variant(jsval_t,VARIANT*) DECLSPEC_HIDDEN; 246 void jsval_release(jsval_t) DECLSPEC_HIDDEN; 247 HRESULT jsval_copy(jsval_t,jsval_t*) DECLSPEC_HIDDEN; 248 249 #endif 250