Ticket #1886: SpiderMonkeyESR24_v0.8.diff
File SpiderMonkeyESR24_v0.8.diff, 165.4 KB (added by , 10 years ago) |
---|
-
build/premake/extern_libs4.lua
Kann nicht anzeigen: Dateityp ist als binär angegeben. svn:mime-type = application/octet-stream Kann nicht anzeigen: Dateityp ist als binär angegeben. svn:mime-type = application/octet-stream
562 562 }, 563 563 spidermonkey = { 564 564 compile_settings = function() 565 if _OPTIONS["with-system-mozjs185"] then 566 if not _OPTIONS["android"] then 567 pkgconfig_cflags("mozjs185") 568 end 569 defines { "WITH_SYSTEM_MOZJS185" } 565 if _OPTIONS["with-system-mozjs24"] then 566 -- to be implemented when such system packages exist 567 --if not _OPTIONS["android"] then 568 -- pkgconfig_cflags("mozjs24") 569 --end 570 --defines { "WITH_SYSTEM_MOZJS24" } 570 571 else 571 572 if os.is("windows") then 572 573 include_dir = "include-win32" 573 574 elseif os.is("macosx") then 574 include_dir = "include "575 include_dir = "include-unix" 575 576 else 576 577 include_dir = "include-unix" 577 578 end 578 579 configuration "Debug" 579 includedirs { libraries_source_dir.."spidermonkey/"..include_dir } 580 includedirs { libraries_source_dir.."spidermonkey/"..include_dir.."-debug" } 581 defines { "DEBUG" } 580 582 configuration "Release" 581 includedirs { libraries_source_dir.."spidermonkey/"..include_dir }583 includedirs { libraries_source_dir.."spidermonkey/"..include_dir.."-release" } 582 584 configuration { } 583 585 end 584 586 end, 585 587 link_settings = function() 586 if _OPTIONS["with-system-mozjs185"] then 587 if _OPTIONS["android"] then 588 links { "mozjs185-1.0" } 589 else 590 pkgconfig_libs("mozjs185") 591 end 588 if _OPTIONS["with-system-mozjs24"] then 589 -- to be implemented when such system packages exist 590 --if _OPTIONS["android"] then 591 -- links { "mozjs185-1.0" } 592 --else 593 -- pkgconfig_libs("mozjs185") 594 --end 592 595 else 593 596 configuration "Debug" 594 links { "mozjs 185-ps-debug" }597 links { "mozjs24-ps-debug" } 595 598 configuration "Release" 596 links { "mozjs 185-ps-release" }599 links { "mozjs24-ps-release" } 597 600 configuration { } 598 601 add_source_lib_paths("spidermonkey") 599 602 end -
build/premake/premake4.lua
15 15 newoption { trigger = "with-system-nvtt", description = "Search standard paths for nvidia-texture-tools library, instead of using bundled copy" } 16 16 newoption { trigger = "with-system-enet", description = "Search standard paths for libenet, instead of using bundled copy" } 17 17 newoption { trigger = "with-system-miniupnpc", description = "Search standard paths for libminiupnpc, instead of using bundled copy" } 18 newoption { trigger = "with-system-mozjs 185", description = "Search standard paths for libmozjs185, instead of using bundled copy" }18 newoption { trigger = "with-system-mozjs24", description = "Search standard paths for libmozjs24, instead of using bundled copy" } 19 19 newoption { trigger = "with-c++11", description = "Enable C++11 on GCC" } 20 20 newoption { trigger = "sysroot", description = "Set compiler system root path, used for building against a non-system SDK. For example /usr/local becomes SYSROOT/user/local" } 21 21 newoption { trigger = "macosx-version-min", description = "Set minimum required version of the OS X API, the build will possibly fail if an older SDK is used, while newer API functions will be weakly linked (i.e. resolved at runtime)" } -
source/simulation2/serialization/BinarySerializer.h
20 20 21 21 #include "ISerializer.h" 22 22 23 #include "scriptinterface/AutoRooters.h"24 25 23 #include "lib/byte_order.h" 26 24 #include "lib/allocators/arena.h" 27 25 … … 73 71 u32 m_ScriptBackrefsNext; 74 72 u32 GetScriptBackrefTag(JSObject* obj); 75 73 76 AutoGCRooter m_Rooter;74 JS::AutoObjectVector m_Rooter; 77 75 78 76 std::map<JSObject*, std::wstring> m_SerializablePrototypes; 79 77 -
source/simulation2/serialization/StdDeserializer.cpp
25 25 #include "scriptinterface/ScriptInterface.h" 26 26 #include "scriptinterface/ScriptExtraHeaders.h" // for typed arrays 27 27 28 #include "js/jsapi.h"29 30 28 #include "lib/byte_order.h" 31 29 32 static uint32 GetJSArrayType(u8 arrayType)33 {34 switch(arrayType)35 {36 case SCRIPT_TYPED_ARRAY_INT8:37 return js::TypedArray::TYPE_INT8;38 case SCRIPT_TYPED_ARRAY_UINT8:39 return js::TypedArray::TYPE_UINT8;40 case SCRIPT_TYPED_ARRAY_INT16:41 return js::TypedArray::TYPE_INT16;42 case SCRIPT_TYPED_ARRAY_UINT16:43 return js::TypedArray::TYPE_UINT16;44 case SCRIPT_TYPED_ARRAY_INT32:45 return js::TypedArray::TYPE_INT32;46 case SCRIPT_TYPED_ARRAY_UINT32:47 return js::TypedArray::TYPE_UINT32;48 case SCRIPT_TYPED_ARRAY_FLOAT32:49 return js::TypedArray::TYPE_FLOAT32;50 case SCRIPT_TYPED_ARRAY_FLOAT64:51 return js::TypedArray::TYPE_FLOAT64;52 case SCRIPT_TYPED_ARRAY_UINT8_CLAMPED:53 return js::TypedArray::TYPE_UINT8_CLAMPED;54 default:55 throw PSERROR_Deserialize_ScriptError("Failed to deserialize unrecognized typed array view");56 }57 }58 59 30 CStdDeserializer::CStdDeserializer(ScriptInterface& scriptInterface, std::istream& stream) : 60 31 m_ScriptInterface(scriptInterface), m_Stream(stream) 61 32 { … … 138 109 139 110 void CStdDeserializer::FreeScriptBackrefs() 140 111 { 112 JSContext* cx = m_ScriptInterface.GetContext(); 113 JSAutoRequest rq(cx); 114 141 115 std::map<u32, JSObject*>::iterator it = m_ScriptBackrefs.begin(); 142 116 for (; it != m_ScriptBackrefs.end(); ++it) 143 117 { 144 if (!JS_RemoveObjectRoot(m_ScriptInterface.GetContext(), &it->second)) 145 throw PSERROR_Deserialize_ScriptError("JS_RemoveRoot failed"); 118 JS_RemoveObjectRoot(m_ScriptInterface.GetContext(), &it->second); 146 119 } 147 120 m_ScriptBackrefs.clear(); 148 121 } … … 152 125 jsval CStdDeserializer::ReadScriptVal(const char* UNUSED(name), JSObject* appendParent) 153 126 { 154 127 JSContext* cx = m_ScriptInterface.GetContext(); 128 129 JSAutoRequest rq(cx); 155 130 156 131 uint8_t type; 157 132 NumberU8_Unbounded("type", type); … … 192 167 if (!proto) 193 168 throw PSERROR_Deserialize_ScriptError("Failed to find serializable prototype for object"); 194 169 195 JSObject* parent = JS_GetParent( cx,proto);170 JSObject* parent = JS_GetParent(proto); 196 171 if (!proto || !parent) 197 172 throw PSERROR_Deserialize_ScriptError(); 198 173 … … 206 181 JSBool hasCustomDeserialize, hasCustomSerialize; 207 182 if (!JS_HasProperty(cx, obj, "Serialize", &hasCustomSerialize) || !JS_HasProperty(cx, obj, "Deserialize", &hasCustomDeserialize)) 208 183 throw PSERROR_Serialize_ScriptError("JS_HasProperty failed"); 209 184 210 185 if (hasCustomDeserialize) 211 186 { 212 jsval serialize;213 if (!JS_LookupProperty(cx, obj, "Serialize", &serialize))187 JS::RootedValue serialize(cx); 188 if (!JS_LookupProperty(cx, obj, "Serialize", serialize.address())) 214 189 throw PSERROR_Serialize_ScriptError("JS_LookupProperty failed"); 215 190 bool hasNullSerialize = hasCustomSerialize && JSVAL_IS_NULL(serialize); 216 191 … … 241 216 utf16string propname; 242 217 ReadStringUTF16("prop name", propname); 243 218 244 jsval propval = ReadScriptVal("prop value", NULL);219 JS::RootedValue propval(cx, ReadScriptVal("prop value", NULL)); 245 220 CScriptValRooted propvalRoot(cx, propval); 246 221 247 if (!JS_SetUCProperty(cx, obj, (const jschar*)propname.data(), propname.length(), &propval))222 if (!JS_SetUCProperty(cx, obj, (const jschar*)propname.data(), propname.length(), propval.address())) 248 223 throw PSERROR_Deserialize_ScriptError(); 249 224 } 250 225 … … 266 241 { 267 242 double value; 268 243 NumberDouble_Unbounded("value", value); 269 jsval rval ;270 if ( !JS_NewNumberValue(cx, value, &rval))244 jsval rval = JS_NumberValue(value); 245 if (JSVAL_IS_NULL(rval)) 271 246 throw PSERROR_Deserialize_ScriptError("JS_NewNumberValue failed"); 272 247 return rval; 273 248 } … … 275 250 { 276 251 uint8_t value; 277 252 NumberU8("value", value, 0, 1); 278 return BOOLEAN_TO_JSVAL(value ? JS_TRUE : JS_FALSE);253 return BOOLEAN_TO_JSVAL(value ? true : false); 279 254 } 280 255 case SCRIPT_TYPE_BACKREF: 281 256 { … … 290 265 { 291 266 double value; 292 267 NumberDouble_Unbounded("value", value); 293 jsval val; 294 if (!JS_NewNumberValue(cx, value, &val)) 295 throw PSERROR_Deserialize_ScriptError(); 268 JS::RootedValue val(cx, JS_NumberValue(value)); 296 269 CScriptValRooted objRoot(cx, val); 297 270 298 271 JSObject* ctorobj; 299 if (!JS_GetClassObject(cx, JS_GetGlobal Object(cx), JSProto_Number, &ctorobj))272 if (!JS_GetClassObject(cx, JS_GetGlobalForScopeChain(cx), JSProto_Number, &ctorobj)) 300 273 throw PSERROR_Deserialize_ScriptError("JS_GetClassObject failed"); 301 274 302 JSObject* obj = JS_New(cx, ctorobj, 1, &val);275 JSObject* obj = JS_New(cx, ctorobj, 1, val.address()); 303 276 if (!obj) 304 277 throw PSERROR_Deserialize_ScriptError("JS_New failed"); 305 278 AddScriptBackref(obj); … … 311 284 ScriptString("value", str); 312 285 if (!str) 313 286 throw PSERROR_Deserialize_ScriptError(); 314 jsval val = STRING_TO_JSVAL(str);287 JS::RootedValue val(cx, STRING_TO_JSVAL(str)); 315 288 CScriptValRooted valRoot(cx, val); 316 289 317 290 JSObject* ctorobj; 318 if (!JS_GetClassObject(cx, JS_GetGlobal Object(cx), JSProto_String, &ctorobj))291 if (!JS_GetClassObject(cx, JS_GetGlobalForScopeChain(cx), JSProto_String, &ctorobj)) 319 292 throw PSERROR_Deserialize_ScriptError("JS_GetClassObject failed"); 320 293 321 JSObject* obj = JS_New(cx, ctorobj, 1, &val);294 JSObject* obj = JS_New(cx, ctorobj, 1, val.address()); 322 295 if (!obj) 323 296 throw PSERROR_Deserialize_ScriptError("JS_New failed"); 324 297 AddScriptBackref(obj); … … 328 301 { 329 302 bool value; 330 303 Bool("value", value); 331 jsval val = BOOLEAN_TO_JSVAL(value ? JS_TRUE : JS_FALSE); 332 CScriptValRooted objRoot(cx, val); 304 JS::RootedValue val(cx, BOOLEAN_TO_JSVAL(value)); 333 305 334 306 JSObject* ctorobj; 335 if (!JS_GetClassObject(cx, JS_GetGlobal Object(cx), JSProto_Boolean, &ctorobj))307 if (!JS_GetClassObject(cx, JS_GetGlobalForScopeChain(cx), JSProto_Boolean, &ctorobj)) 336 308 throw PSERROR_Deserialize_ScriptError("JS_GetClassObject failed"); 337 309 338 JSObject* obj = JS_New(cx, ctorobj, 1, &val);310 JSObject* obj = JS_New(cx, ctorobj, 1, val.address()); 339 311 if (!obj) 340 312 throw PSERROR_Deserialize_ScriptError("JS_New failed"); 341 313 AddScriptBackref(obj); … … 354 326 355 327 // Get buffer object 356 328 jsval bufferVal = ReadScriptVal("buffer", NULL); 357 CScriptValRooted bufferValRoot(cx, bufferVal);358 329 359 if ( !JSVAL_IS_OBJECT(bufferVal))330 if (JSVAL_IS_PRIMITIVE(bufferVal)) 360 331 throw PSERROR_Deserialize_ScriptError(); 361 332 362 333 JSObject* bufferObj = JSVAL_TO_OBJECT(bufferVal); 363 if (! js_IsArrayBuffer(bufferObj))334 if (!JS_IsArrayBufferObject(bufferObj)) 364 335 throw PSERROR_Deserialize_ScriptError("js_IsArrayBuffer failed"); 365 336 366 JSObject* arrayObj = js_CreateTypedArrayWithBuffer(cx, GetJSArrayType(arrayType), bufferObj, byteOffset, length); 337 JSObject* arrayObj; 338 switch(arrayType) 339 { 340 case SCRIPT_TYPED_ARRAY_INT8: 341 arrayObj = JS_NewInt8ArrayWithBuffer(cx, bufferObj, byteOffset, length); 342 break; 343 case SCRIPT_TYPED_ARRAY_UINT8: 344 arrayObj = JS_NewUint8ArrayWithBuffer(cx, bufferObj, byteOffset, length); 345 break; 346 case SCRIPT_TYPED_ARRAY_INT16: 347 arrayObj = JS_NewInt16ArrayWithBuffer(cx, bufferObj, byteOffset, length); 348 break; 349 case SCRIPT_TYPED_ARRAY_UINT16: 350 arrayObj = JS_NewUint16ArrayWithBuffer(cx, bufferObj, byteOffset, length); 351 break; 352 case SCRIPT_TYPED_ARRAY_INT32: 353 arrayObj = JS_NewInt32ArrayWithBuffer(cx, bufferObj, byteOffset, length); 354 break; 355 case SCRIPT_TYPED_ARRAY_UINT32: 356 arrayObj = JS_NewUint32ArrayWithBuffer(cx, bufferObj, byteOffset, length); 357 break; 358 case SCRIPT_TYPED_ARRAY_FLOAT32: 359 arrayObj = JS_NewFloat32ArrayWithBuffer(cx, bufferObj, byteOffset, length); 360 break; 361 case SCRIPT_TYPED_ARRAY_FLOAT64: 362 arrayObj = JS_NewFloat64ArrayWithBuffer(cx, bufferObj, byteOffset, length); 363 break; 364 case SCRIPT_TYPED_ARRAY_UINT8_CLAMPED: 365 arrayObj = JS_NewUint8ClampedArrayWithBuffer(cx, bufferObj, byteOffset, length); 366 break; 367 default: 368 throw PSERROR_Deserialize_ScriptError("Failed to deserialize unrecognized typed array view"); 369 } 367 370 if (!arrayObj) 368 371 throw PSERROR_Deserialize_ScriptError("js_CreateTypedArrayWithBuffer failed"); 369 372 … … 383 386 #error TODO: need to convert JS ArrayBuffer data from little-endian 384 387 #endif 385 388 386 JSObject* bufferObj = js_CreateArrayBuffer(cx, length); 387 if (!bufferObj) 388 throw PSERROR_Deserialize_ScriptError("js_CreateArrayBuffer failed"); 389 389 JSObject* bufferObj = JS_NewArrayBufferWithContents(cx, (void*)bufferData); 390 390 AddScriptBackref(bufferObj); 391 391 392 js::ArrayBuffer* buffer = js::ArrayBuffer::fromJSObject(bufferObj);393 memcpy(buffer->data, bufferData, length);394 delete[] bufferData;395 396 392 return OBJECT_TO_JSVAL(bufferObj); 397 393 } 398 394 default: … … 440 436 441 437 void CStdDeserializer::ScriptObjectAppend(const char* name, jsval& obj) 442 438 { 443 if ( !JSVAL_IS_OBJECT(obj))439 if (JSVAL_IS_PRIMITIVE(obj)) 444 440 throw PSERROR_Deserialize_ScriptError(); 445 441 446 442 ReadScriptVal(name, JSVAL_TO_OBJECT(obj)); -
source/simulation2/serialization/BinarySerializer.cpp
19 19 20 20 #include "BinarySerializer.h" 21 21 22 #include "SerializedScriptTypes.h"23 24 22 #include "lib/alignment.h" 25 23 #include "ps/CLogger.h" 26 24 27 25 #include "scriptinterface/ScriptInterface.h" 28 26 #include "scriptinterface/ScriptExtraHeaders.h" // for JSDOUBLE_IS_INT32, typed arrays 27 #include "SerializedScriptTypes.h" 29 28 30 static u8 GetArrayType( uint32arrayType)29 static u8 GetArrayType(JSArrayBufferViewType arrayType) 31 30 { 32 31 switch(arrayType) 33 32 { 34 case js::TypedArray::TYPE_INT8:33 case JSArrayBufferViewType::TYPE_INT8: 35 34 return SCRIPT_TYPED_ARRAY_INT8; 36 case js::TypedArray::TYPE_UINT8:35 case JSArrayBufferViewType::TYPE_UINT8: 37 36 return SCRIPT_TYPED_ARRAY_UINT8; 38 case js::TypedArray::TYPE_INT16:37 case JSArrayBufferViewType::TYPE_INT16: 39 38 return SCRIPT_TYPED_ARRAY_INT16; 40 case js::TypedArray::TYPE_UINT16:39 case JSArrayBufferViewType::TYPE_UINT16: 41 40 return SCRIPT_TYPED_ARRAY_UINT16; 42 case js::TypedArray::TYPE_INT32:41 case JSArrayBufferViewType::TYPE_INT32: 43 42 return SCRIPT_TYPED_ARRAY_INT32; 44 case js::TypedArray::TYPE_UINT32:43 case JSArrayBufferViewType::TYPE_UINT32: 45 44 return SCRIPT_TYPED_ARRAY_UINT32; 46 case js::TypedArray::TYPE_FLOAT32:45 case JSArrayBufferViewType::TYPE_FLOAT32: 47 46 return SCRIPT_TYPED_ARRAY_FLOAT32; 48 case js::TypedArray::TYPE_FLOAT64:47 case JSArrayBufferViewType::TYPE_FLOAT64: 49 48 return SCRIPT_TYPED_ARRAY_FLOAT64; 50 case js::TypedArray::TYPE_UINT8_CLAMPED:49 case JSArrayBufferViewType::TYPE_UINT8_CLAMPED: 51 50 return SCRIPT_TYPED_ARRAY_UINT8_CLAMPED; 52 51 default: 53 52 LOGERROR(L"Cannot serialize unrecognized typed array view: %d", arrayType); … … 56 55 } 57 56 58 57 CBinarySerializerScriptImpl::CBinarySerializerScriptImpl(ScriptInterface& scriptInterface, ISerializer& serializer) : 59 m_ScriptInterface(scriptInterface), m_Serializer(serializer), m_Rooter(m_ScriptInterface ),58 m_ScriptInterface(scriptInterface), m_Serializer(serializer), m_Rooter(m_ScriptInterface.GetContext()), 60 59 m_ScriptBackrefsArena(1 * MiB), m_ScriptBackrefs(backrefs_t::key_compare(), ScriptBackrefsAlloc(m_ScriptBackrefsArena)), m_ScriptBackrefsNext(1) 61 60 { 62 61 } 63 62 // TODO YGW: Test serialization... 64 63 void CBinarySerializerScriptImpl::HandleScriptVal(jsval val) 65 64 { 66 65 JSContext* cx = m_ScriptInterface.GetContext(); 66 JSAutoRequest rq(cx); 67 67 68 68 switch (JS_TypeOfValue(cx, val)) 69 69 { … … 85 85 break; 86 86 } 87 87 88 JSObject* obj = JSVAL_TO_OBJECT(val); 88 //JSObject* obj = JSVAL_TO_OBJECT(val); 89 JS::RootedObject obj(cx, JSVAL_TO_OBJECT(val)); 89 90 90 91 // If we've already serialized this object, just output a reference to it 91 92 u32 tag = GetScriptBackrefTag(obj); … … 104 105 105 106 // Arrays like [1, 2, ] have an 'undefined' at the end which is part of the 106 107 // length but seemingly isn't enumerated, so store the length explicitly 107 jsuint length = 0;108 uint length = 0; 108 109 if (!JS_GetArrayLength(cx, obj, &length)) 109 110 throw PSERROR_Serialize_ScriptError("JS_GetArrayLength failed"); 110 111 m_Serializer.NumberU32_Unbounded("array length", length); 111 112 } 112 else if (js_IsTypedArray(obj)) 113 //JS_IsArrayBufferViewObject() 114 //JS_IsTypedArrayObject() 115 else if (JS_IsTypedArrayObject(obj)) 113 116 { 114 117 m_Serializer.NumberU8_Unbounded("type", SCRIPT_TYPE_TYPED_ARRAY); 115 118 116 js::TypedArray* typedArray = js::TypedArray::fromJSObject(obj); 117 118 m_Serializer.NumberU8_Unbounded("array type", GetArrayType(typedArray->type)); 119 m_Serializer.NumberU32_Unbounded("byte offset", typedArray->byteOffset); 120 m_Serializer.NumberU32_Unbounded("length", typedArray->length); 119 m_Serializer.NumberU8_Unbounded("array type", GetArrayType(JS_GetArrayBufferViewType(obj))); 120 m_Serializer.NumberU32_Unbounded("byte offset", JS_GetTypedArrayByteOffset(obj)); 121 m_Serializer.NumberU32_Unbounded("length", JS_GetTypedArrayLength(obj)); 121 122 122 123 // Now handle its array buffer 123 124 // this may be a backref, since ArrayBuffers can be shared by multiple views 124 HandleScriptVal(OBJECT_TO_JSVAL( typedArray->bufferJS));125 HandleScriptVal(OBJECT_TO_JSVAL(JS_GetArrayBufferViewBuffer(obj))); 125 126 break; 126 127 } 127 else if ( js_IsArrayBuffer(obj))128 else if (JS_IsArrayBufferObject(obj)) 128 129 { 129 130 m_Serializer.NumberU8_Unbounded("type", SCRIPT_TYPE_ARRAY_BUFFER); 130 131 131 js::ArrayBuffer* arrayBuffer = js::ArrayBuffer::fromJSObject(obj);132 133 132 #if BYTE_ORDER != LITTLE_ENDIAN 134 133 #error TODO: need to convert JS ArrayBuffer data to little-endian 135 134 #endif 136 135 137 u32 length = arrayBuffer->byteLength;136 u32 length = JS_GetArrayBufferByteLength(obj); 138 137 m_Serializer.NumberU32_Unbounded("buffer length", length); 139 m_Serializer.RawBytes("buffer data", (const u8*) arrayBuffer->data, length);138 m_Serializer.RawBytes("buffer data", (const u8*)JS_GetArrayBufferData(obj), length); 140 139 break; 141 140 } 142 141 else 143 142 { 144 143 // Find type of object 145 JSClass* jsclass = JS_G ET_CLASS(cx,obj);144 JSClass* jsclass = JS_GetClass(obj); 146 145 if (!jsclass) 147 throw PSERROR_Serialize_ScriptError("JS_G ET_CLASSfailed");146 throw PSERROR_Serialize_ScriptError("JS_GetClass failed"); 148 147 JSProtoKey protokey = JSCLASS_CACHED_PROTO_KEY(jsclass); 149 148 150 149 if (protokey == JSProto_Object) 151 150 { 152 151 // Object class - check for user-defined prototype 153 JSObject* proto = JS_GetPrototype(cx, obj); 152 JS::RootedObject proto(cx); 153 JS_GetPrototype(cx, obj, proto.address()); 154 154 if (!proto) 155 155 throw PSERROR_Serialize_ScriptError("JS_GetPrototype failed"); 156 156 … … 175 175 JSBool hasCustomSerialize; 176 176 if (!JS_HasProperty(cx, obj, "Serialize", &hasCustomSerialize)) 177 177 throw PSERROR_Serialize_ScriptError("JS_HasProperty failed"); 178 178 179 179 if (hasCustomSerialize) 180 180 { 181 jsval serialize;182 if (!JS_LookupProperty(cx, obj, "Serialize", &serialize))181 JS::RootedValue serialize(cx); 182 if (!JS_LookupProperty(cx, obj, "Serialize", serialize.address())) 183 183 throw PSERROR_Serialize_ScriptError("JS_LookupProperty failed"); 184 184 185 185 // If serialize is null, so don't serialize anything more … … 199 199 // Standard Number object 200 200 m_Serializer.NumberU8_Unbounded("type", SCRIPT_TYPE_OBJECT_NUMBER); 201 201 // Get primitive value 202 jsdouble d;202 double d; 203 203 if (!JS_ValueToNumber(cx, val, &d)) 204 204 throw PSERROR_Serialize_ScriptError("JS_ValueToNumber failed"); 205 205 m_Serializer.NumberDouble_Unbounded("value", d); … … 224 224 JSBool b; 225 225 if (!JS_ValueToBoolean(cx, val, &b)) 226 226 throw PSERROR_Serialize_ScriptError("JS_ValueToBoolean failed"); 227 m_Serializer.Bool("value", b == JS_TRUE);227 m_Serializer.Bool("value", b); 228 228 break; 229 229 } 230 230 else … … 240 240 // (Note that we don't do any rooting, because we assume nothing is going to trigger GC. 241 241 // I'm not absolute certain that's necessarily a valid assumption.) 242 242 243 AutoJSIdArray ida (cx, JS_Enumerate(cx, obj));244 if (!ida .get())243 JS::AutoIdArray ida (cx, JS_Enumerate(cx, obj)); 244 if (!ida) 245 245 throw PSERROR_Serialize_ScriptError("JS_Enumerate failed"); 246 246 247 247 m_Serializer.NumberU32_Unbounded("num props", (uint32_t)ida.length()); … … 250 250 { 251 251 jsid id = ida[i]; 252 252 253 jsval idval, propval; 254 253 JS::RootedValue idval(cx); 254 JS::RootedValue propval(cx); 255 255 256 // Get the property name as a string 256 if (!JS_IdToValue(cx, id, &idval))257 if (!JS_IdToValue(cx, id, idval.address())) 257 258 throw PSERROR_Serialize_ScriptError("JS_IdToValue failed"); 258 JSString* idstr = JS_ValueToString(cx, idval );259 JSString* idstr = JS_ValueToString(cx, idval.get()); 259 260 if (!idstr) 260 261 throw PSERROR_Serialize_ScriptError("JS_ValueToString failed"); 261 262 … … 263 264 264 265 // Use LookupProperty instead of GetProperty to avoid the danger of getters 265 266 // (they might delete values and trigger GC) 266 if (!JS_LookupPropertyById(cx, obj, id, &propval))267 if (!JS_LookupPropertyById(cx, obj, id, propval.address())) 267 268 throw PSERROR_Serialize_ScriptError("JS_LookupPropertyById failed"); 268 269 269 270 HandleScriptVal(propval); … … 308 309 else 309 310 { 310 311 ENSURE(JSVAL_IS_DOUBLE(val)); 311 312 // If the value fits in an int, serialise as an int 313 jsdouble d = JSVAL_TO_DOUBLE(val); 314 int32_t i; 315 if (JSDOUBLE_IS_INT32(d, &i)) 316 { 317 m_Serializer.NumberU8_Unbounded("type", SCRIPT_TYPE_INT); 318 m_Serializer.NumberI32_Unbounded("value", i); 319 } 320 // Otherwise serialise as a double 321 else 322 { 323 m_Serializer.NumberU8_Unbounded("type", SCRIPT_TYPE_DOUBLE); 324 m_Serializer.NumberDouble_Unbounded("value", d); 325 } 312 m_Serializer.NumberU8_Unbounded("type", SCRIPT_TYPE_DOUBLE); 313 m_Serializer.NumberDouble_Unbounded("value", JSVAL_TO_DOUBLE(val)); 326 314 } 327 315 break; 328 316 } 329 317 case JSTYPE_BOOLEAN: 330 318 { 331 319 m_Serializer.NumberU8_Unbounded("type", SCRIPT_TYPE_BOOLEAN); 332 JSBool b = JSVAL_TO_BOOLEAN(val);320 bool b = JSVAL_TO_BOOLEAN(val); 333 321 m_Serializer.NumberU8_Unbounded("value", b ? 1 : 0); 334 322 break; 335 323 } 336 case JSTYPE_XML:337 {338 LOGERROR(L"Cannot serialise JS objects of type 'xml'");339 throw PSERROR_Serialize_InvalidScriptValue();340 }341 324 default: 342 325 { 343 326 debug_warn(L"Invalid TypeOfValue"); … … 349 332 void CBinarySerializerScriptImpl::ScriptString(const char* name, JSString* string) 350 333 { 351 334 JSContext* cx = m_ScriptInterface.GetContext(); 335 JSAutoRequest rq(cx); 336 352 337 size_t length; 353 338 const jschar* chars = JS_GetStringCharsAndLength(cx, string, &length); 354 339 … … 382 367 383 368 // If it was newly inserted, we need to make sure it gets rooted 384 369 // for the duration that it's in m_ScriptBackrefs 385 m_Rooter.Push(it.first->first); 370 // Note: Spidermonkey has a moving GC. JSObject pointers in this mapping table can change, 371 // but we have registered a custom trace call for the time m_ScriptBackrefs is alive which 372 // takes care of updating the pointers in our mapping table. 373 // TODO: Could this be bad for GC-Performance if we serialize large objects and keep the Serializer 374 // (including m_ScriptBackrefs) alive? Do we keep it alive somewhere? 375 m_Rooter.append(it.first->first); 386 376 m_ScriptBackrefsNext++; 387 377 // Return a non-tag number so callers know they need to serialize the object 388 378 return 0; -
source/simulation2/system/ComponentManager.cpp
243 243 244 244 // Find all the ctor prototype's On* methods, and subscribe to the appropriate messages: 245 245 246 CScriptVal proto;246 JS::RootedObject proto(componentManager->m_ScriptInterface.GetContext()); 247 247 if (!componentManager->m_ScriptInterface.GetProperty(ctor.get(), "prototype", proto)) 248 248 return; // error 249 249 250 250 std::vector<std::string> methods; 251 if (!componentManager->m_ScriptInterface.EnumeratePropertyNamesWithPrefix(proto .get(), "On", methods))251 if (!componentManager->m_ScriptInterface.EnumeratePropertyNamesWithPrefix(proto, "On", methods)) 252 252 return; // error 253 253 254 254 for (std::vector<std::string>::const_iterator it = methods.begin(); it != methods.end(); ++it) … … 289 289 { 290 290 jsval instance = eit->second->GetJSInstance(); 291 291 if (!JSVAL_IS_NULL(instance)) 292 componentManager->m_ScriptInterface.SetPrototype(instance, proto.get()); 292 { 293 JS::RootedObject instanceObj(componentManager->m_ScriptInterface.GetContext(),&instance.toObject()); 294 componentManager->m_ScriptInterface.SetPrototype(instanceObj, proto); 295 } 293 296 } 294 297 } 295 298 } … … 616 619 jsval obj = JSVAL_NULL; 617 620 if (ct.type == CT_Script) 618 621 { 619 obj = m_ScriptInterface.CallConstructor(ct.ctor.get(), JSVAL_VOID);622 obj = m_ScriptInterface.CallConstructor(ct.ctor.get(), 0, JSVAL_VOID); 620 623 if (JSVAL_IS_VOID(obj)) 621 624 { 622 625 LOGERROR(L"Script component constructor failed"); -
source/simulation2/system/InterfaceScripted.h
19 19 #define INCLUDED_INTERFACE_SCRIPTED 20 20 21 21 #include "scriptinterface/ScriptInterface.h" 22 #include "js/jsapi.h"23 22 24 23 #define BEGIN_INTERFACE_WRAPPER(iname) \ 25 24 JSClass class_ICmp##iname = { \ 26 25 "ICmp" #iname, JSCLASS_HAS_PRIVATE, \ 27 JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub, \ 28 JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub, \ 29 JSCLASS_NO_OPTIONAL_MEMBERS \ 26 JS_PropertyStub, JS_DeletePropertyStub, JS_PropertyStub, JS_StrictPropertyStub, \ 27 JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub \ 30 28 }; \ 31 29 static JSFunctionSpec methods_ICmp##iname[] = { 32 30 … … 35 33 }; \ 36 34 void ICmp##iname::InterfaceInit(ScriptInterface& scriptInterface) { \ 37 35 JSContext* cx = scriptInterface.GetContext(); \ 38 JSObject* global = JS_GetGlobalObject(cx); \ 36 JSAutoRequest rq(cx); \ 37 JSObject* global = JS_GetGlobalForScopeChain(cx); \ 39 38 JS_InitClass(cx, global, NULL, &class_ICmp##iname, NULL, 0, NULL, methods_ICmp##iname, NULL, NULL); \ 40 39 } \ 41 40 JSClass* ICmp##iname::GetJSClass() const { return &class_ICmp##iname; } \ … … 45 44 46 45 #define DEFINE_INTERFACE_METHOD_0(scriptname, rettype, classname, methodname) \ 47 46 { scriptname, \ 48 ScriptInterface::callMethod<rettype, &class_##classname, classname, &classname::methodname>, \47 { ScriptInterface::callMethod<rettype, &class_##classname, classname, &classname::methodname>, NULL }, \ 49 48 0, \ 50 49 JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT }, 51 50 52 51 #define DEFINE_INTERFACE_METHOD_1(scriptname, rettype, classname, methodname, arg1) \ 53 52 { scriptname, \ 54 ScriptInterface::callMethod<rettype, arg1, &class_##classname, classname, &classname::methodname>, \53 { ScriptInterface::callMethod<rettype, arg1, &class_##classname, classname, &classname::methodname>, NULL}, \ 55 54 1, \ 56 55 JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT }, 57 56 58 57 #define DEFINE_INTERFACE_METHOD_2(scriptname, rettype, classname, methodname, arg1, arg2) \ 59 58 { scriptname, \ 60 ScriptInterface::callMethod<rettype, arg1, arg2, &class_##classname, classname, &classname::methodname>, \59 { ScriptInterface::callMethod<rettype, arg1, arg2, &class_##classname, classname, &classname::methodname>, NULL }, \ 61 60 2, \ 62 61 JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT }, 63 62 64 63 #define DEFINE_INTERFACE_METHOD_3(scriptname, rettype, classname, methodname, arg1, arg2, arg3) \ 65 64 { scriptname, \ 66 ScriptInterface::callMethod<rettype, arg1, arg2, arg3, &class_##classname, classname, &classname::methodname>, \65 { ScriptInterface::callMethod<rettype, arg1, arg2, arg3, &class_##classname, classname, &classname::methodname>, NULL }, \ 67 66 3, \ 68 67 JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT }, 69 68 70 69 #define DEFINE_INTERFACE_METHOD_4(scriptname, rettype, classname, methodname, arg1, arg2, arg3, arg4) \ 71 70 { scriptname, \ 72 ScriptInterface::callMethod<rettype, arg1, arg2, arg3, arg4, &class_##classname, classname, &classname::methodname>, \71 { ScriptInterface::callMethod<rettype, arg1, arg2, arg3, arg4, &class_##classname, classname, &classname::methodname>, NULL }, \ 73 72 4, \ 74 73 JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT }, 75 74 76 75 #define DEFINE_INTERFACE_METHOD_5(scriptname, rettype, classname, methodname, arg1, arg2, arg3, arg4, arg5) \ 77 76 { scriptname, \ 78 ScriptInterface::callMethod<rettype, arg1, arg2, arg3, arg4, arg5, &class_##classname, classname, &classname::methodname>, \77 { ScriptInterface::callMethod<rettype, arg1, arg2, arg3, arg4, arg5, &class_##classname, classname, &classname::methodname>, NULL }, \ 79 78 5, \ 80 79 JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT }, 81 80 82 81 #define DEFINE_INTERFACE_METHOD_6(scriptname, rettype, classname, methodname, arg1, arg2, arg3, arg4, arg5, arg6) \ 83 82 { scriptname, \ 84 ScriptInterface::callMethod<rettype, arg1, arg2, arg3, arg4, arg5, arg6, &class_##classname, classname, &classname::methodname>, \83 { ScriptInterface::callMethod<rettype, arg1, arg2, arg3, arg4, arg5, arg6, &class_##classname, classname, &classname::methodname>, NULL }, \ 85 84 6, \ 86 85 JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT }, 87 86 88 87 #define DEFINE_INTERFACE_METHOD_7(scriptname, rettype, classname, methodname, arg1, arg2, arg3, arg4, arg5, arg6, arg7) \ 89 88 { scriptname, \ 90 ScriptInterface::callMethod<rettype, arg1, arg2, arg3, arg4, arg5, arg6, arg7, &class_##classname, classname, &classname::methodname>, \89 { ScriptInterface::callMethod<rettype, arg1, arg2, arg3, arg4, arg5, arg6, arg7, &class_##classname, classname, &classname::methodname>, NULL }, \ 91 90 7, \ 92 91 JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT }, 93 92 -
source/simulation2/system/ParamNode.cpp
25 25 #include "ps/Filesystem.h" 26 26 #include "ps/XML/Xeromyces.h" 27 27 28 #include "js/jsapi.h"29 30 28 #include <sstream> 31 29 32 30 // Disable "'boost::algorithm::detail::is_classifiedF' : assignment operator could not be generated" … … 328 326 329 327 jsval CParamNode::ConstructJSVal(JSContext* cx) const 330 328 { 329 JSAutoRequest rq(cx); 331 330 if (m_Childs.empty()) 332 331 { 333 332 // Empty node - map to undefined … … 351 350 352 351 for (std::map<std::string, CParamNode>::const_iterator it = m_Childs.begin(); it != m_Childs.end(); ++it) 353 352 { 354 jsval childVal = it->second.ConstructJSVal(cx);355 if (!JS_SetProperty(cx, obj, it->first.c_str(), &childVal))353 JS::RootedValue childVal(cx, it->second.ConstructJSVal(cx)); 354 if (!JS_SetProperty(cx, obj, it->first.c_str(), childVal.address())) 356 355 return JSVAL_VOID; // TODO: report error 357 356 } 358 357 … … 363 362 JSString* str = JS_InternUCStringN(cx, reinterpret_cast<const jschar*>(text.data()), text.length()); 364 363 if (!str) 365 364 return JSVAL_VOID; // TODO: report error 366 jsval childVal = STRING_TO_JSVAL(str);367 if (!JS_SetProperty(cx, obj, "_string", &childVal))365 JS::RootedValue childVal(cx, STRING_TO_JSVAL(str)); 366 if (!JS_SetProperty(cx, obj, "_string", childVal.address())) 368 367 return JSVAL_VOID; // TODO: report error 369 368 } 370 369 -
source/simulation2/system/ComponentManager.h
96 96 void RegisterComponentType(InterfaceId, ComponentTypeId, AllocFunc, DeallocFunc, const char*, const std::string& schema); 97 97 void RegisterComponentTypeScriptWrapper(InterfaceId, ComponentTypeId, AllocFunc, DeallocFunc, const char*, const std::string& schema); 98 98 99 100 void Tick() { m_ScriptInterface.Tick(); }; 99 101 /** 100 102 * Subscribe the current component type to the given message type. 101 103 * Each component's HandleMessage will be called on any BroadcastMessage of this message type, -
source/simulation2/components/CCmpAIManager.cpp
152 152 ENSURE(m_Worker.m_HasLoadedEntityTemplates); 153 153 m_ScriptInterface->SetProperty(settings.get(), "templates", m_Worker.m_EntityTemplates, false); 154 154 155 obj = m_ScriptInterface->CallConstructor(ctor.get(), settings.get()); 155 JS::AutoValueVector argv(m_ScriptInterface->GetContext()); 156 argv.append(settings.get()); 157 obj = m_ScriptInterface->CallConstructor(ctor.get(), argv.length(), argv.handleAt(0)); 156 158 } 157 159 else 158 160 { … … 209 211 }; 210 212 211 213 CAIWorker() : 212 // TODO: Passing a 32 MB argument to CreateRuntime() is a temporary fix 213 // to prevent frequent AI out-of-memory crashes. The argument should be 214 // removed as soon whenever the new pathfinder is committed 215 // And the AIs can stop relying on their own little hands. 216 m_ScriptRuntime(ScriptInterface::CreateRuntime(33554432)), 217 m_ScriptInterface(new ScriptInterface("Engine", "AI", m_ScriptRuntime)), 214 m_ScriptInterface(new ScriptInterface("Engine", "AI", g_ScriptRuntime)), 218 215 m_TurnNum(0), 219 216 m_CommandsComputed(true), 220 217 m_HasLoadedEntityTemplates(false), … … 305 302 static void ForceGC(ScriptInterface::CxPrivate* pCxPrivate) 306 303 { 307 304 PROFILE3("AI compute GC"); 308 JS_GC(pCxPrivate->pScriptInterface->Get Context());305 JS_GC(pCxPrivate->pScriptInterface->GetJSRuntime()); 309 306 } 310 307 311 308 /** … … 408 405 m_ScriptInterface->Eval("({})", fakeTech); 409 406 m_ScriptInterface->SetProperty(settings.get(), "techTemplates", fakeTech, false); 410 407 } 411 m_SharedAIObj = CScriptValRooted(m_ScriptInterface->GetContext(),m_ScriptInterface->CallConstructor(ctor.get(), settings.get())); 408 409 JS::AutoValueVector argv(m_ScriptInterface->GetContext()); 410 argv.append(settings.get()); 411 m_SharedAIObj = CScriptValRooted(m_ScriptInterface->GetContext(),m_ScriptInterface->CallConstructor(ctor.get(), argv.length(), argv.handleAt(0))); 412 412 413 413 414 414 if (m_SharedAIObj.undefined()) … … 754 754 m_Players[i]->Run(state, m_Players[i]->m_Player); 755 755 } 756 756 757 /* 757 758 // Run GC if we are about to overflow 758 759 if (JS_GetGCParameter(m_ScriptInterface->GetJSRuntime(), JSGC_BYTES) > 33000000) 759 760 { 760 761 PROFILE3("AI compute GC"); 761 762 762 JS_GC(m_ScriptInterface->Get Context());763 JS_GC(m_ScriptInterface->GetJSRuntime()); 763 764 } 764 765 */ 765 766 // Run the GC every so often. 766 767 // (This isn't particularly necessary, but it makes profiling clearer 767 768 // since it avoids random GC delays while running other scripts) -
source/simulation2/components/ICmpFootprint.cpp
38 38 39 39 if (shape == CIRCLE) 40 40 { 41 jsval ptype = ScriptInterface::ToJSVal<std::string>(cx, "circle");42 jsval pradius = ScriptInterface::ToJSVal(cx, size0);43 jsval pheight = ScriptInterface::ToJSVal(cx, height);44 JS_SetProperty(cx, obj, "type", &ptype);45 JS_SetProperty(cx, obj, "radius", &pradius);46 JS_SetProperty(cx, obj, "height", &pheight);41 JS::RootedValue ptype(cx, ScriptInterface::ToJSVal<std::string>(cx, "circle")); 42 JS::RootedValue pradius(cx, ScriptInterface::ToJSVal(cx, size0)); 43 JS::RootedValue pheight(cx, ScriptInterface::ToJSVal(cx, height)); 44 JS_SetProperty(cx, obj, "type", ptype.address()); 45 JS_SetProperty(cx, obj, "radius", pradius.address()); 46 JS_SetProperty(cx, obj, "height", pheight.address()); 47 47 } 48 48 else 49 49 { 50 jsval ptype = ScriptInterface::ToJSVal<std::string>(cx, "square");51 jsval pwidth = ScriptInterface::ToJSVal(cx, size0);52 jsval pdepth = ScriptInterface::ToJSVal(cx, size1);53 jsval pheight = ScriptInterface::ToJSVal(cx, height);54 JS_SetProperty(cx, obj, "type", &ptype);55 JS_SetProperty(cx, obj, "width", &pwidth);56 JS_SetProperty(cx, obj, "depth", &pdepth);57 JS_SetProperty(cx, obj, "height", &pheight);50 JS::RootedValue ptype(cx, ScriptInterface::ToJSVal<std::string>(cx, "square")); 51 JS::RootedValue pwidth(cx, ScriptInterface::ToJSVal(cx, size0)); 52 JS::RootedValue pdepth(cx, ScriptInterface::ToJSVal(cx, size1)); 53 JS::RootedValue pheight(cx, ScriptInterface::ToJSVal(cx, height)); 54 JS_SetProperty(cx, obj, "type", ptype.address()); 55 JS_SetProperty(cx, obj, "width", pwidth.address()); 56 JS_SetProperty(cx, obj, "depth", pdepth.address()); 57 JS_SetProperty(cx, obj, "height", pheight.address()); 58 58 } 59 59 60 60 return OBJECT_TO_JSVAL(obj); -
source/simulation2/Simulation2.cpp
155 155 } 156 156 157 157 int ProgressiveLoad(); 158 159 void Tick(); 158 160 void Update(int turnLength, const std::vector<SimulationCommand>& commands); 159 161 static void UpdateComponents(CSimContext& simContext, fixed turnLengthFixed, const std::vector<SimulationCommand>& commands); 160 162 void Interpolate(float simFrameLength, float frameOffset, float realFrameLength); … … 336 338 debug_warn(L"Serialization test failure"); 337 339 } 338 340 341 void CSimulation2Impl::Tick() 342 { 343 m_ComponentManager.Tick(); 344 } 345 339 346 void CSimulation2Impl::Update(int turnLength, const std::vector<SimulationCommand>& commands) 340 347 { 341 348 PROFILE3("sim update"); … … 637 644 return m->m_ComponentManager.GetEntitiesWithInterfaceUnordered(iid); 638 645 } 639 646 647 void CSimulation2::Tick() 648 { 649 m->Tick(); 650 } 651 640 652 const CSimContext& CSimulation2::GetSimContext() const 641 653 { 642 654 return m->m_SimContext; -
source/simulation2/Simulation2.h
53 53 ~CSimulation2(); 54 54 55 55 void EnableOOSLog(); 56 void Tick(); 56 57 void EnableSerializationTest(); 57 58 58 59 /** -
source/simulation2/scripting/MessageTypeConversions.cpp
21 21 #include "scriptinterface/ScriptInterface.h" 22 22 #include "simulation2/MessageTypes.h" 23 23 24 #include "js/jsapi.h"25 26 24 #define TOJSVAL_SETUP() \ 27 JSObject* obj = JS_NewObject(scriptInterface.GetContext(), NULL, NULL, NULL); \ 28 if (! obj) \ 29 return JSVAL_VOID; 25 JSObject* obj; \ 26 {\ 27 JSAutoRequest rq(scriptInterface.GetContext()); \ 28 obj = JS_NewObject(scriptInterface.GetContext(), NULL, NULL, NULL); \ 29 if (!obj) \ 30 return JSVAL_VOID; \ 31 } 30 32 31 33 #define SET_MSG_PROPERTY(name) \ 32 34 do { \ 33 jsval prop = ScriptInterface::ToJSVal(scriptInterface.GetContext(), this->name); \ 34 if (! JS_SetProperty(scriptInterface.GetContext(), obj, #name, &prop)) \ 35 JSAutoRequest rq(scriptInterface.GetContext()); \ 36 JSContext* cx = scriptInterface.GetContext(); \ 37 JS::RootedValue prop(cx, ScriptInterface::ToJSVal(cx, this->name)); \ 38 if (! JS_SetProperty(cx, obj, #name, prop.address())) \ 35 39 return JSVAL_VOID; \ 36 40 } while (0); 37 41 38 42 #define FROMJSVAL_SETUP() \ 39 if ( ! JSVAL_IS_OBJECT(val)) \43 if ( JSVAL_IS_PRIMITIVE(val)) \ 40 44 return NULL; \ 41 45 JSObject* obj = JSVAL_TO_OBJECT(val); \ 42 jsval prop;46 JS::RootedValue prop(scriptInterface.GetContext()); 43 47 44 48 #define GET_MSG_PROPERTY(type, name) \ 45 if (! JS_GetProperty(scriptInterface.GetContext(), obj, #name, &prop)) \ 49 type name; \ 50 { \ 51 JSAutoRequest rq(scriptInterface.GetContext()); \ 52 if (! JS_GetProperty(scriptInterface.GetContext(), obj, #name, prop.address())) \ 46 53 return NULL; \ 47 type name;\48 if (! ScriptInterface::FromJSVal(scriptInterface.GetContext(), prop, name))\49 return NULL;54 if (! ScriptInterface::FromJSVal(scriptInterface.GetContext(), prop.get(), name)) \ 55 return NULL; \ 56 } 50 57 51 58 jsval CMessage::ToJSValCached(ScriptInterface& scriptInterface) const 52 59 { -
source/simulation2/scripting/EngineScriptConversions.cpp
34 34 35 35 template<> jsval ScriptInterface::ToJSVal<IComponent*>(JSContext* cx, IComponent* const& val) 36 36 { 37 JSAutoRequest rq(cx); 37 38 if (val == NULL) 38 39 return JSVAL_NULL; 39 40 … … 58 59 LOGERROR(L"Failed to construct IComponent script object"); 59 60 return JSVAL_VOID; 60 61 } 61 JS_SetPrivate( cx,obj, static_cast<void*>(val));62 JS_SetPrivate(obj, static_cast<void*>(val)); 62 63 63 64 return OBJECT_TO_JSVAL(obj); 64 65 } 65 66 66 67 template<> jsval ScriptInterface::ToJSVal<CParamNode>(JSContext* cx, CParamNode const& val) 67 68 { 69 JSAutoRequest rq(cx); 68 70 jsval rval = val.ToJSVal(cx, true); 69 71 70 72 // Prevent modifications to the object, so that it's safe to share between 71 73 // components and to reconstruct on deserialization 72 if ( JSVAL_IS_OBJECT(rval))74 if (!JSVAL_IS_PRIMITIVE(rval)) 73 75 JS_DeepFreezeObject(cx, JSVAL_TO_OBJECT(rval)); 74 76 75 77 return rval; … … 85 87 86 88 template<> bool ScriptInterface::FromJSVal<CColor>(JSContext* cx, jsval v, CColor& out) 87 89 { 88 if ( !JSVAL_IS_OBJECT(v))90 if (JSVAL_IS_PRIMITIVE(v)) 89 91 FAIL("jsval not an object"); 90 92 93 JSAutoRequest rq(cx); 91 94 JSObject* obj = JSVAL_TO_OBJECT(v); 92 95 93 jsval r, g, b, a; 94 if (!JS_GetProperty(cx, obj, "r", &r) || !FromJSVal(cx, r, out.r)) 96 JS::RootedValue r(cx); 97 JS::RootedValue g(cx); 98 JS::RootedValue b(cx); 99 JS::RootedValue a(cx); 100 if (!JS_GetProperty(cx, obj, "r", r.address()) || !FromJSVal(cx, r, out.r)) 95 101 FAIL("Failed to get property CColor.r"); 96 if (!JS_GetProperty(cx, obj, "g", &g) || !FromJSVal(cx, g, out.g))102 if (!JS_GetProperty(cx, obj, "g", g.address()) || !FromJSVal(cx, g, out.g)) 97 103 FAIL("Failed to get property CColor.g"); 98 if (!JS_GetProperty(cx, obj, "b", &b) || !FromJSVal(cx, b, out.b))104 if (!JS_GetProperty(cx, obj, "b", b.address()) || !FromJSVal(cx, b, out.b)) 99 105 FAIL("Failed to get property CColor.b"); 100 if (!JS_GetProperty(cx, obj, "a", &a) || !FromJSVal(cx, a, out.a))106 if (!JS_GetProperty(cx, obj, "a", a.address()) || !FromJSVal(cx, a, out.a)) 101 107 FAIL("Failed to get property CColor.a"); 102 108 // TODO: this probably has GC bugs if a getter returns an unrooted value 103 109 … … 106 112 107 113 template<> jsval ScriptInterface::ToJSVal<CColor>(JSContext* cx, CColor const& val) 108 114 { 115 JSAutoRequest rq(cx); 109 116 JSObject* obj = JS_NewObject(cx, NULL, NULL, NULL); 110 117 if (!obj) 111 118 return JSVAL_VOID; 112 119 113 jsval r = ToJSVal(cx, val.r);114 jsval g = ToJSVal(cx, val.g);115 jsval b = ToJSVal(cx, val.b);116 jsval a = ToJSVal(cx, val.a);120 JS::RootedValue r(cx, ToJSVal(cx, val.r)); 121 JS::RootedValue g(cx, ToJSVal(cx, val.g)); 122 JS::RootedValue b(cx, ToJSVal(cx, val.b)); 123 JS::RootedValue a(cx, ToJSVal(cx, val.a)); 117 124 118 JS_SetProperty(cx, obj, "r", &r);119 JS_SetProperty(cx, obj, "g", &g);120 JS_SetProperty(cx, obj, "b", &b);121 JS_SetProperty(cx, obj, "a", &a);125 JS_SetProperty(cx, obj, "r", r.address()); 126 JS_SetProperty(cx, obj, "g", g.address()); 127 JS_SetProperty(cx, obj, "b", b.address()); 128 JS_SetProperty(cx, obj, "a", a.address()); 122 129 123 130 return OBJECT_TO_JSVAL(obj); 124 131 } 125 132 126 133 template<> bool ScriptInterface::FromJSVal<fixed>(JSContext* cx, jsval v, fixed& out) 127 134 { 128 jsdouble ret; 135 JSAutoRequest rq(cx); 136 double ret; 129 137 if (!JS_ValueToNumber(cx, v, &ret)) 130 138 return false; 131 139 out = fixed::FromDouble(ret); … … 134 142 return true; 135 143 } 136 144 137 template<> jsval ScriptInterface::ToJSVal<fixed>(JSContext* cx, const fixed& val)145 template<> jsval ScriptInterface::ToJSVal<fixed>(JSContext* UNUSED(cx), const fixed& val) 138 146 { 139 jsval rval = JSVAL_VOID; 140 JS_NewNumberValue(cx, val.ToDouble(), &rval); // ignore return value 147 jsval rval = JS_NumberValue(val.ToDouble()); 141 148 return rval; 142 149 } 143 150 144 151 template<> bool ScriptInterface::FromJSVal<CFixedVector3D>(JSContext* cx, jsval v, CFixedVector3D& out) 145 152 { 146 if ( !JSVAL_IS_OBJECT(v))153 if (JSVAL_IS_PRIMITIVE(v)) 147 154 return false; // TODO: report type error 155 156 JSAutoRequest rq(cx); 148 157 JSObject* obj = JSVAL_TO_OBJECT(v); 149 158 150 jsval p;159 JS::RootedValue p(cx); 151 160 152 if (!JS_GetProperty(cx, obj, "x", &p)) return false; // TODO: report type errors161 if (!JS_GetProperty(cx, obj, "x", p.address())) return false; // TODO: report type errors 153 162 if (!FromJSVal(cx, p, out.X)) return false; 154 163 155 if (!JS_GetProperty(cx, obj, "y", &p)) return false;164 if (!JS_GetProperty(cx, obj, "y", p.address())) return false; 156 165 if (!FromJSVal(cx, p, out.Y)) return false; 157 166 158 if (!JS_GetProperty(cx, obj, "z", &p)) return false;167 if (!JS_GetProperty(cx, obj, "z", p.address())) return false; 159 168 if (!FromJSVal(cx, p, out.Z)) return false; 160 169 161 170 return true; … … 163 172 164 173 template<> jsval ScriptInterface::ToJSVal<CFixedVector3D>(JSContext* cx, const CFixedVector3D& val) 165 174 { 175 JSAutoRequest rq(cx); 166 176 JSObject* obj = JS_NewObject(cx, NULL, NULL, NULL); 167 177 if (!obj) 168 178 return JSVAL_VOID; 169 179 170 jsval x = ToJSVal(cx, val.X);171 jsval y = ToJSVal(cx, val.Y);172 jsval z = ToJSVal(cx, val.Z);180 JS::RootedValue x(cx, ToJSVal(cx, val.X)); 181 JS::RootedValue y(cx, ToJSVal(cx, val.Y)); 182 JS::RootedValue z(cx, ToJSVal(cx, val.Z)); 173 183 174 JS_SetProperty(cx, obj, "x", &x);175 JS_SetProperty(cx, obj, "y", &y);176 JS_SetProperty(cx, obj, "z", &z);184 JS_SetProperty(cx, obj, "x", x.address()); 185 JS_SetProperty(cx, obj, "y", y.address()); 186 JS_SetProperty(cx, obj, "z", z.address()); 177 187 178 188 return OBJECT_TO_JSVAL(obj); 179 189 } 180 190 181 191 template<> bool ScriptInterface::FromJSVal<CFixedVector2D>(JSContext* cx, jsval v, CFixedVector2D& out) 182 192 { 183 if (!JSVAL_IS_OBJECT(v)) 193 JSAutoRequest rq(cx); 194 if (JSVAL_IS_PRIMITIVE(v)) 184 195 return false; // TODO: report type error 185 196 JSObject* obj = JSVAL_TO_OBJECT(v); 186 197 187 jsval p;198 JS::RootedValue p(cx); 188 199 189 if (!JS_GetProperty(cx, obj, "x", &p)) return false; // TODO: report type errors200 if (!JS_GetProperty(cx, obj, "x", p.address())) return false; // TODO: report type errors 190 201 if (!FromJSVal(cx, p, out.X)) return false; 191 202 192 if (!JS_GetProperty(cx, obj, "y", &p)) return false;203 if (!JS_GetProperty(cx, obj, "y", p.address())) return false; 193 204 if (!FromJSVal(cx, p, out.Y)) return false; 194 205 195 206 return true; … … 197 208 198 209 template<> jsval ScriptInterface::ToJSVal<CFixedVector2D>(JSContext* cx, const CFixedVector2D& val) 199 210 { 211 JSAutoRequest rq(cx); 200 212 JSObject* obj = JS_NewObject(cx, NULL, NULL, NULL); 201 213 if (!obj) 202 214 return JSVAL_VOID; 203 215 204 jsval x = ToJSVal(cx, val.X);205 jsval y = ToJSVal(cx, val.Y);216 JS::RootedValue x(cx, ToJSVal(cx, val.X)); 217 JS::RootedValue y(cx, ToJSVal(cx, val.Y)); 206 218 207 JS_SetProperty(cx, obj, "x", &x);208 JS_SetProperty(cx, obj, "y", &y);219 JS_SetProperty(cx, obj, "x", x.address()); 220 JS_SetProperty(cx, obj, "y", y.address()); 209 221 210 222 return OBJECT_TO_JSVAL(obj); 211 223 } 212 224 213 template< jsint atype, typename T> jsval ToJSVal_Grid(JSContext* cx, const Grid<T>& val)225 template<> jsval ScriptInterface::ToJSVal<Grid<u8> >(JSContext* cx, const Grid<u8>& val) 214 226 { 215 JSObject* obj = JS_NewObject(cx, NULL, NULL, NULL); 216 if (!obj) 217 return JSVAL_VOID; 227 JSAutoRequest rq(cx); 228 uint32_t length = (uint32_t)(val.m_W * val.m_H); 229 uint32_t nbytes = (uint32_t)(length * sizeof(uint8_t)); 230 JSObject* objArr = JS_NewUint8Array(cx, length); 231 memcpy((void*)JS_GetUint8ArrayData(objArr), val.m_Data, nbytes); 218 232 219 jsuint len = val.m_W * val.m_H; 220 JSObject *darray = js_CreateTypedArray(cx, atype, len); 221 if (!darray) 222 return JSVAL_VOID; 233 JS::RootedValue data(cx, OBJECT_TO_JSVAL(objArr)); 234 JS::RootedValue w(cx, ScriptInterface::ToJSVal(cx, val.m_W)); 235 JS::RootedValue h(cx, ScriptInterface::ToJSVal(cx, val.m_H)); 223 236 224 js::TypedArray *tdest = js::TypedArray::fromJSObject(darray);225 ENSURE(tdest->byteLength == len*sizeof(T));226 237 227 memcpy(tdest->data, val.m_Data, tdest->byteLength); 238 JSObject* obj = JS_NewObject(cx, NULL, NULL, NULL); 239 JS_SetProperty(cx, obj, "width", w.address()); 240 JS_SetProperty(cx, obj, "height", h.address()); 241 JS_SetProperty(cx, obj, "data", data.address()); 228 242 229 jsval w = ScriptInterface::ToJSVal(cx, val.m_W);230 jsval h = ScriptInterface::ToJSVal(cx, val.m_H);231 jsval data = OBJECT_TO_JSVAL(darray);232 233 JS_SetProperty(cx, obj, "width", &w);234 JS_SetProperty(cx, obj, "height", &h);235 JS_SetProperty(cx, obj, "data", &data);236 237 243 return OBJECT_TO_JSVAL(obj); 238 244 } 245 246 template<> jsval ScriptInterface::ToJSVal<Grid<u16> >(JSContext* cx, const Grid<u16>& val) 247 { 248 JSAutoRequest rq(cx); 249 uint32_t length = (uint32_t)(val.m_W * val.m_H); 250 uint32_t nbytes = (uint32_t)(length * sizeof(uint16_t)); 251 JSObject* objArr = JS_NewUint16Array(cx, length); 252 memcpy((void*)JS_GetUint16ArrayData(objArr), val.m_Data, nbytes); 253 254 JS::RootedValue data(cx, OBJECT_TO_JSVAL(objArr)); 255 JS::RootedValue w(cx, ScriptInterface::ToJSVal(cx, val.m_W)); 256 JS::RootedValue h(cx, ScriptInterface::ToJSVal(cx, val.m_H)); 239 257 240 template<> jsval ScriptInterface::ToJSVal<Grid<u8> >(JSContext* cx, const Grid<u8>& val) 241 { 242 return ToJSVal_Grid<js::TypedArray::TYPE_UINT8>(cx, val);243 } 258 JSObject* obj = JS_NewObject(cx, NULL, NULL, NULL); 259 JS_SetProperty(cx, obj, "width", w.address()); 260 JS_SetProperty(cx, obj, "height", h.address()); 261 JS_SetProperty(cx, obj, "data", data.address()); 244 262 245 template<> jsval ScriptInterface::ToJSVal<Grid<u16> >(JSContext* cx, const Grid<u16>& val) 246 { 247 return ToJSVal_Grid<js::TypedArray::TYPE_UINT16>(cx, val); 263 return OBJECT_TO_JSVAL(obj); 248 264 } -
source/lobby/XmppClient.cpp
284 284 void XmppClient::SendIqGameReport(ScriptInterface& scriptInterface, CScriptVal data) 285 285 { 286 286 glooxwrapper::JID xpartamuppJid(m_xpartamuppId); 287 jsval dataval = data.get();287 JS::RootedValue dataval(scriptInterface.GetContext(), data.get()); 288 288 289 289 // Setup some base stanza attributes 290 290 GameReport* game = new GameReport(); … … 292 292 293 293 // Iterate through all the properties reported and add them to the stanza. 294 294 std::vector<std::string> properties; 295 scriptInterface.EnumeratePropertyNamesWithPrefix( dataval, "", properties);295 scriptInterface.EnumeratePropertyNamesWithPrefix(JS::RootedObject(scriptInterface.GetContext(), JSVAL_TO_OBJECT(dataval)), "", properties); 296 296 for (std::vector<int>::size_type i = 0; i != properties.size(); i++) 297 297 { 298 298 std::wstring value; … … 318 318 void XmppClient::SendIqRegisterGame(ScriptInterface& scriptInterface, CScriptVal data) 319 319 { 320 320 glooxwrapper::JID xpartamuppJid(m_xpartamuppId); 321 jsval dataval = data.get();321 JS::RootedValue dataval(scriptInterface.GetContext(), data.get()); 322 322 323 323 // Setup some base stanza attributes 324 324 GameListQuery* g = new GameListQuery(); … … 329 329 330 330 // Iterate through all the properties reported and add them to the stanza. 331 331 std::vector<std::string> properties; 332 scriptInterface.EnumeratePropertyNamesWithPrefix(dataval, "", properties); 332 JS::RootedObject dataobj(scriptInterface.GetContext(), JSVAL_TO_OBJECT(dataval.get())); 333 scriptInterface.EnumeratePropertyNamesWithPrefix(dataobj, "", properties); 333 334 for (std::vector<int>::size_type i = 0; i != properties.size(); i++) 334 335 { 335 336 std::wstring value; -
source/ps/scripting/JSInterface_VFS.cpp
68 68 { 69 69 BuildDirEntListState* s = (BuildDirEntListState*)cbData; 70 70 71 jsval val = ScriptInterface::ToJSVal(s->cx, CStrW(pathname.string()));72 JS_SetElement(s->cx, s->filename_array, s->cur_idx++, &val);71 JS::RootedValue val(s->cx, ScriptInterface::ToJSVal( s->cx, CStrW(pathname.string()) )); 72 JS_SetElement(s->cx, s->filename_array, s->cur_idx++, val.address()); 73 73 return INFO::OK; 74 74 } 75 75 … … 191 191 while (std::getline(ss, line)) 192 192 { 193 193 // Decode each line as UTF-8 194 jsval val = ScriptInterface::ToJSVal(cx, CStr(line).FromUTF8());195 JS_SetElement(cx, line_array, cur_line++, &val);194 JS::RootedValue val(cx, ScriptInterface::ToJSVal(cx, CStr(line).FromUTF8())); 195 JS_SetElement(cx, line_array, cur_line++, val.address()); 196 196 } 197 197 198 198 return OBJECT_TO_JSVAL( line_array ); -
source/ps/Profile.cpp
29 29 # define USE_CRT_SET_ALLOC_HOOK 30 30 #endif 31 31 32 #if defined(__GLIBC__) && !defined(NDEBUG)33 // # define USE_GLIBC_MALLOC_HOOK34 # define USE_GLIBC_MALLOC_OVERRIDE35 # include <dlfcn.h>36 # include <malloc.h>37 # include "lib/sysdep/cpu.h"38 #endif32 //#if defined(__GLIBC__) && !defined(NDEBUG) 33 ////# define USE_GLIBC_MALLOC_HOOK 34 //# define USE_GLIBC_MALLOC_OVERRIDE 35 //# include <dlfcn.h> 36 //# include <malloc.h> 37 //# include "lib/sysdep/cpu.h" 38 //#endif 39 39 40 40 #include <numeric> 41 41 -
source/ps/GameSetup/GameSetup.cpp
1099 1099 CStr seedArg = args.Get("autostart-random"); 1100 1100 1101 1101 // Default seed is 0 1102 uint32 seed = 0;1102 uint32_t seed = 0; 1103 1103 if (!seedArg.empty()) 1104 1104 { 1105 1105 if (seedArg.compare("-1") == 0) -
source/ps/Errors.h
72 72 73 73 #include <exception> 74 74 75 typedef u32 PSRETURN; 75 //typedef u32 PSRETURN; 76 typedef uint32_t PSRETURN; 76 77 77 78 class PSERROR : public std::exception 78 79 { -
source/ps/Replay.cpp
127 127 new CProfileManager; 128 128 g_ScriptStatsTable = new CScriptStatsTable; 129 129 g_ProfileViewer.AddRootTable(g_ScriptStatsTable); 130 g_ScriptRuntime = ScriptInterface::CreateRuntime( 128* 1024 * 1024);130 g_ScriptRuntime = ScriptInterface::CreateRuntime(256 * 1024 * 1024); 131 131 132 132 CGame game(true); 133 133 g_Game = &game; … … 210 210 g_Profiler2.IncrementFrameNumber(); 211 211 PROFILE2_ATTR("%d", g_Profiler2.GetFrameNumber()); 212 212 213 game.GetSimulation2()->Tick(); 213 214 game.GetSimulation2()->Update(turnLength, commands); 214 215 commands.clear(); 215 216 } -
source/scriptinterface/ScriptExtraHeaders.h
31 31 # endif 32 32 # pragma GCC diagnostic ignored "-Wunused-parameter" 33 33 # pragma GCC diagnostic ignored "-Wredundant-decls" 34 # pragma GCC diagnostic ignored "-Wnon-virtual-dtor" 34 35 # if GCC_VERSION >= 408 35 36 # pragma GCC diagnostic ignored "-Wunused-local-typedefs" // caused by js/debug.h 36 37 # endif … … 46 47 # define signbit std::signbit 47 48 #endif 48 49 49 #include "js/jstypedarray.h" 50 #include "js/jsdbgapi.h" 50 //#include "js/jstypedarray.h" 51 //#include "jspubtd.h" 52 //#include "jsatom.h" 53 #include "jsfriendapi.h" 54 #include "jsdbgapi.h" 51 55 52 56 #undef signbit 53 57 … … 57 61 #if GCC_VERSION >= 402 58 62 # pragma GCC diagnostic warning "-Wunused-parameter" 59 63 # pragma GCC diagnostic warning "-Wredundant-decls" 64 # pragma GCC diagnostic warning "-Wnon-virtual-dtor" 60 65 # if GCC_VERSION >= 406 61 66 # pragma GCC diagnostic pop // restore user flags 62 67 # endif -
source/scriptinterface/ScriptVal.h
58 58 */ 59 59 jsval get() const; 60 60 61 void Wrap(JSContext* cx); 62 61 63 /** 62 64 * Returns reference to the current value. 63 65 * Fails if the value is not yet initialised. 64 66 */ 65 67 jsval& getRef() const; 66 68 69 void getPtr(JS::Value** val); 70 67 71 /** 68 72 * Returns whether the value is uninitialised or is JSVAL_VOID. 69 73 */ -
source/scriptinterface/tests/test_ScriptConversions.h
23 23 #include "maths/MathUtil.h" 24 24 #include "ps/CLogger.h" 25 25 26 #include "js /jsapi.h"26 #include "jsapi.h" 27 27 28 28 class TestScriptConversions : public CxxTest::TestSuite 29 29 { … … 38 38 // We want to convert values to strings, but can't just call toSource() on them 39 39 // since they might not be objects. So just use uneval. 40 40 std::string source; 41 TS_ASSERT(script.CallFunction(OBJECT_TO_JSVAL(JS_GetGlobal Object(cx)), "uneval", CScriptVal(v1), source));41 TS_ASSERT(script.CallFunction(OBJECT_TO_JSVAL(JS_GetGlobalForScopeChain(cx)), "uneval", CScriptVal(v1), source)); 42 42 43 43 TS_ASSERT_STR_EQUALS(source, expected); 44 44 } … … 52 52 jsval v1 = ScriptInterface::ToJSVal(cx, value); 53 53 54 54 std::string source; 55 TS_ASSERT(script.CallFunction(OBJECT_TO_JSVAL(JS_GetGlobal Object(cx)), "uneval", CScriptVal(v1), source));55 TS_ASSERT(script.CallFunction(OBJECT_TO_JSVAL(JS_GetGlobalForScopeChain(cx)), "uneval", CScriptVal(v1), source)); 56 56 57 57 if (expected) 58 58 TS_ASSERT_STR_EQUALS(source, expected); -
source/scriptinterface/tests/test_ScriptVal.h
20 20 #include "scriptinterface/ScriptInterface.h" 21 21 #include "scriptinterface/ScriptVal.h" 22 22 23 #include "js /jsapi.h"23 #include "jsapi.h" 24 24 25 25 class TestScriptVal : public CxxTest::TestSuite 26 26 { … … 35 35 36 36 CScriptValRooted root(cx, OBJECT_TO_JSVAL(obj)); 37 37 38 JS_GC( cx);38 JS_GC(script.GetRuntime()); 39 39 40 40 jsval val = INT_TO_JSVAL(123); 41 41 TS_ASSERT(JS_SetProperty(cx, obj, "test", &val)); 42 42 43 JS_GC( cx);43 JS_GC(script.GetRuntime()); 44 44 45 45 jsval rval; 46 46 TS_ASSERT(JS_GetProperty(cx, obj, "test", &rval)); -
source/scriptinterface/AutoRooters.cpp
1 /* Copyright (C) 2010 Wildfire Games.2 * This file is part of 0 A.D.3 *4 * 0 A.D. is free software: you can redistribute it and/or modify5 * it under the terms of the GNU General Public License as published by6 * the Free Software Foundation, either version 2 of the License, or7 * (at your option) any later version.8 *9 * 0 A.D. is distributed in the hope that it will be useful,10 * but WITHOUT ANY WARRANTY; without even the implied warranty of11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12 * GNU General Public License for more details.13 *14 * You should have received a copy of the GNU General Public License15 * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.16 */17 18 #include "precompiled.h"19 20 #include "AutoRooters.h"21 22 #include "scriptinterface/ScriptInterface.h"23 24 AutoGCRooter::AutoGCRooter(ScriptInterface& scriptInterface)25 : m_ScriptInterface(scriptInterface)26 {27 m_Previous = m_ScriptInterface.ReplaceAutoGCRooter(this);28 }29 30 AutoGCRooter::~AutoGCRooter()31 {32 AutoGCRooter* r = m_ScriptInterface.ReplaceAutoGCRooter(m_Previous);33 ENSURE(r == this); // must be correctly nested34 }35 36 void AutoGCRooter::Trace(JSTracer* trc)37 {38 if (m_Previous)39 m_Previous->Trace(trc);40 41 for (size_t i = 0; i < m_Objects.size(); ++i)42 {43 JS_CALL_OBJECT_TRACER(trc, m_Objects[i], "AutoGCRooter object");44 }45 46 for (size_t i = 0; i < m_Vals.size(); ++i)47 {48 JS_CALL_VALUE_TRACER(trc, m_Vals[i], "AutoGCRooter val");49 }50 51 for (size_t i = 0; i < m_IdArrays.size(); ++i)52 {53 for (jsint j = 0; j < m_IdArrays[i]->length; ++j)54 {55 jsval val = JSVAL_VOID;56 JS_IdToValue(m_ScriptInterface.GetContext(), m_IdArrays[i]->vector[j], &val);57 JS_CALL_VALUE_TRACER(trc, val, "AutoGCRooter id array");58 }59 }60 61 } -
source/scriptinterface/ScriptInterface.h
25 25 #include "ScriptTypes.h" 26 26 #include "ScriptVal.h" 27 27 28 #include "js/jsapi.h"29 30 28 #include "ps/Errors.h" 31 29 ERROR_GROUP(Scripting); 32 30 ERROR_TYPE(Scripting, SetupFailed); … … 52 50 53 51 #include <boost/random/linear_congruential.hpp> 54 52 55 class AutoGCRooter;56 57 53 // Set the maximum number of function arguments that can be handled 58 54 // (This should be as small as possible (for compiler efficiency), 59 55 // but as large as necessary for all wrapped functions) … … 114 110 void* pCBData; // meant to be used as the "this" object for callback functions 115 111 } m_CxPrivate; 116 112 113 void Tick(); 117 114 void SetCallbackData(void* pCBData); 118 115 static CxPrivate* GetScriptInterfaceAndCBData(JSContext* cx); 119 116 … … 136 133 * Call a constructor function, equivalent to JS "new ctor(arg)". 137 134 * @return The new object; or JSVAL_VOID on failure, and logs an error message 138 135 */ 139 jsval CallConstructor(jsval ctor, jsval arg);136 jsval CallConstructor(jsval ctor, int argc, jsval argv); 140 137 141 138 /** 142 139 * Create an object as with CallConstructor except don't actually execute the … … 251 248 */ 252 249 bool HasProperty(jsval obj, const char* name); 253 250 254 bool EnumeratePropertyNamesWithPrefix( jsvalobj, const char* prefix, std::vector<std::string>& out);251 bool EnumeratePropertyNamesWithPrefix(JS::HandleObject obj, const char* prefix, std::vector<std::string>& out); 255 252 256 bool SetPrototype( jsval obj, jsvalproto);253 bool SetPrototype(JS::HandleObject obj, JS::HandleObject proto); 257 254 258 255 bool FreezeObject(jsval obj, bool deep); 259 256 … … 326 323 */ 327 324 template<typename T> static jsval ToJSVal(JSContext* cx, T const& val); 328 325 329 AutoGCRooter* ReplaceAutoGCRooter(AutoGCRooter* rooter);330 331 326 /** 332 327 * Dump some memory heap debugging information to stderr. 333 328 */ … … 338 333 */ 339 334 void MaybeGC(); 340 335 336 bool MathRandom(double& nbr); 337 341 338 /** 342 339 * Structured clones are a way to serialize 'simple' JS values into a buffer 343 340 * that can safely be passed between contexts and runtimes and threads. … … 351 348 public: 352 349 StructuredClone(); 353 350 ~StructuredClone(); 354 JSContext* m_Context; 355 uint64* m_Data; 351 uint64_t* m_Data; 356 352 size_t m_Size; 357 353 }; 358 354 … … 367 363 bool SetProperty_(jsval obj, const char* name, jsval value, bool readonly, bool enumerate); 368 364 bool SetProperty_(jsval obj, const wchar_t* name, jsval value, bool readonly, bool enumerate); 369 365 bool SetPropertyInt_(jsval obj, int name, jsval value, bool readonly, bool enumerate); 370 bool GetProperty_(jsval obj, const char* name, jsval& value);371 bool GetPropertyInt_(jsval obj, int name, jsval&value);366 bool GetProperty_(jsval obj, const char* name, JS::MutableHandleValue out); 367 bool GetPropertyInt_(jsval obj, int name, JS::MutableHandleValue value); 372 368 static bool IsExceptionPending(JSContext* cx); 373 static JSClass* GetClass(JS Context* cx, JSObject* obj);374 static void* GetPrivate(JS Context* cx, JSObject* obj);369 static JSClass* GetClass(JSObject* obj); 370 static void* GetPrivate(JSObject* obj); 375 371 376 372 class CustomType 377 373 { … … 383 379 void Register(const char* name, JSNative fptr, size_t nargs); 384 380 std::auto_ptr<ScriptInterface_impl> m; 385 381 382 boost::rand48* m_rng; 386 383 std::map<std::string, CustomType> m_CustomObjectTypes; 387 384 388 385 // The nasty macro/template bits are split into a separate file so you don't have to look at them … … 527 524 template<typename T> 528 525 bool ScriptInterface::GetProperty(jsval obj, const char* name, T& out) 529 526 { 530 jsval val; 531 if (! GetProperty_(obj, name, val)) 527 JSContext* cx = GetContext(); 528 JSAutoRequest rq(cx); 529 JS::RootedValue val(cx); 530 if (! GetProperty_(obj, name, &val)) 532 531 return false; 533 return FromJSVal( GetContext(), val, out);532 return FromJSVal(cx, val, out); 534 533 } 535 534 536 535 template<typename T> 537 536 bool ScriptInterface::GetPropertyInt(jsval obj, int name, T& out) 538 537 { 539 jsval val;540 if (! GetPropertyInt_(obj, name, val))538 JS::RootedValue val(GetContext()); 539 if (! GetPropertyInt_(obj, name, &val)) 541 540 return false; 542 541 return FromJSVal(GetContext(), val, out); 543 542 } -
source/scriptinterface/ScriptTypes.h
33 33 // the ones that are needed and this avoids conflicting definitions 34 34 # define JS_SYS_TYPES_H_DEFINES_EXACT_SIZE_TYPES 35 35 36 36 37 #else // If not Windows, then Unix: 37 38 38 39 # define XP_UNIX 39 40 40 // In DEBUG mode, jsval defaults to struct types. Normally we build separate41 // debug/release mode versions of the library, but when using --with-system-mozjs18542 // it's always a release mode library, so we have to disable struct types for43 // ABI compatibility44 # if defined(DEBUG) && defined(WITH_SYSTEM_MOZJS185)45 # define JS_NO_JSVAL_JSID_STRUCT_TYPES46 # endif47 48 41 #endif 49 42 // (we don't support XP_OS2 or XP_BEOS) 50 43 51 44 52 45 // Guess whether the library was compiled with the release-mode or debug-mode ABI 53 46 // (for JS_DumpHeap etc) 54 #if defined(DEBUG) && !defined(WITH_SYSTEM_MOZJS 185)47 #if defined(DEBUG) && !defined(WITH_SYSTEM_MOZJS24) 55 48 # define MOZJS_DEBUG_ABI 1 56 49 #else 57 50 # define MOZJS_DEBUG_ABI 0 58 51 #endif 59 52 60 61 // SpiderMonkey wants the DEBUG flag62 #ifndef NDEBUG63 # ifndef DEBUG64 # define DEBUG65 # endif66 #endif67 68 53 // Ignore some harmless warnings triggered by jsapi.h 69 #if GCC_VERSION >= 402 // (older GCCs don't support this pragma) 54 // TODO: Optimize this for different GCC versions if we find a list which pragma is supported in which version of GCC) 55 // Also some versions of GCC will still print warnings (see http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53431). 56 #if GCC_VERSION >= 402 70 57 # pragma GCC diagnostic ignored "-Wunused-parameter" 71 58 # pragma GCC diagnostic ignored "-Wredundant-decls" 59 # pragma GCC diagnostic ignored "-Wundef" 60 # pragma GCC diagnostic ignored "-Wignored-qualifiers" 61 # pragma GCC diagnostic ignored "-Wnon-virtual-dtor" 72 62 #endif 73 63 #if MSC_VERSION 74 64 # pragma warning(push) … … 76 66 # pragma warning(disable:4100) // "unreferenced formal parameter" 77 67 #endif 78 68 79 #include "js/jsapi.h" 69 #include "jspubtd.h" 70 #include "jsapi.h" 80 71 72 81 73 #if MSC_VERSION 82 74 # pragma warning(pop) 83 75 #endif 84 76 #if GCC_VERSION >= 402 85 77 # pragma GCC diagnostic warning "-Wunused-parameter" 86 78 # pragma GCC diagnostic warning "-Wredundant-decls" 79 # pragma GCC diagnostic warning "-Wundef" 80 # pragma GCC diagnostic warning "-Wignored-qualifiers" 81 # pragma GCC diagnostic warning "-Wnon-virtual-dtor" 87 82 #endif 88 83 89 #if JS_VERSION != 185 90 #error Your compiler is trying to use an incorrect version of the SpiderMonkey library.91 #error The only version that works is the one in the libraries/spidermonkey/ directory,92 #error and it will not work with a typical system-installed version.93 #error Make sure you have got all the right files and include paths.94 #endif84 //#if MOZJS_MAJOR_VERSION != 24 || MOZJS_MINOR_VERSION != 0 85 //#error Your compiler is trying to use an incorrect version of the SpiderMonkey library. 86 //#error The only version that works is the one in the libraries/spidermonkey/ directory, 87 //#error and it will not work with a typical system-installed version. 88 //#error Make sure you have got all the right files and include paths. 89 //#endif 95 90 96 91 class ScriptInterface; 97 92 class CScriptVal; -
source/scriptinterface/NativeWrapperDecls.h
26 26 #define NUMBERED_LIST_BALANCED(z, i, data) BOOST_PP_COMMA_IF(i) data##i 27 27 // Some other things 28 28 #define TYPED_ARGS(z, i, data) , T##i a##i 29 #define CONVERT_ARG(z, i, data) T##i a##i; if (! ScriptInterface::FromJSVal<T##i>(cx, i < argc ? JS_ARGV(cx, vp)[i] : JSVAL_VOID, a##i)) return JS_FALSE;29 #define CONVERT_ARG(z, i, data) T##i a##i; if (! ScriptInterface::FromJSVal<T##i>(cx, i < argc ? JS_ARGV(cx, vp)[i] : JSVAL_VOID, a##i)) return false; 30 30 31 31 // List-generating macros, named roughly after their first list item 32 32 #define TYPENAME_T0_HEAD(z, i) BOOST_PP_REPEAT_##z (i, NUMBERED_LIST_HEAD, typename T) // "typename T0, typename T1, " … … 51 51 // (Definition comes later, since it depends on some things we haven't defined yet) 52 52 #define OVERLOADS(z, i, data) \ 53 53 template <typename R, TYPENAME_T0_HEAD(z,i) R (*fptr) ( ScriptInterface::CxPrivate* T0_TAIL(z,i) )> \ 54 static JSBool call(JSContext* cx, uint Nargc, jsval* vp);54 static JSBool call(JSContext* cx, uint32_t argc, jsval* vp); 55 55 BOOST_PP_REPEAT(SCRIPT_INTERFACE_MAX_ARGS, OVERLOADS, ~) 56 56 #undef OVERLOADS 57 57 58 58 // Similar, for class methods 59 59 #define OVERLOADS(z, i, data) \ 60 60 template <typename R, TYPENAME_T0_HEAD(z,i) JSClass* CLS, typename TC, R (TC::*fptr) ( T0(z,i) )> \ 61 static JSBool callMethod(JSContext* cx, uint Nargc, jsval* vp);61 static JSBool callMethod(JSContext* cx, uint32_t argc, jsval* vp); 62 62 BOOST_PP_REPEAT(SCRIPT_INTERFACE_MAX_ARGS, OVERLOADS, ~) 63 63 #undef OVERLOADS 64 64 -
source/scriptinterface/ScriptVal.cpp
17 17 18 18 #include "precompiled.h" 19 19 20 #include "ScriptInterface.h" 20 21 #include "ScriptVal.h" 21 22 22 #include "js/jsapi.h"23 23 24 24 struct Unrooter 25 25 { 26 26 Unrooter(JSContext* cx) : cx(cx) { } 27 void operator()(jsval* p) { JS_RemoveValueRoot(cx, p); delete p; } 27 void operator()(jsval* p) 28 { 29 JSAutoRequest rq(cx); 30 JS_RemoveValueRoot(cx, p); delete p; 31 } 28 32 JSContext* cx; 29 33 }; 30 34 31 35 CScriptValRooted::CScriptValRooted(JSContext* cx, jsval val) 32 36 { 37 JSAutoRequest rq(cx); 33 38 jsval* p = new jsval(val); 34 39 JS_AddNamedValueRoot(cx, p, "CScriptValRooted"); 35 40 m_Val = boost::shared_ptr<jsval>(p, Unrooter(cx)); … … 37 42 38 43 CScriptValRooted::CScriptValRooted(JSContext* cx, CScriptVal val) 39 44 { 45 JSAutoRequest rq(cx); 40 46 jsval* p = new jsval(val.get()); 41 47 JS_AddNamedValueRoot(cx, p, "CScriptValRooted"); 42 48 m_Val = boost::shared_ptr<jsval>(p, Unrooter(cx)); … … 49 55 return *m_Val; 50 56 } 51 57 58 void CScriptValRooted::getPtr(JS::Value** val) 59 { 60 *val = &*m_Val; 61 } 62 52 63 jsval& CScriptValRooted::getRef() const 53 64 { 54 65 ENSURE(m_Val); … … 65 76 return !m_Val; 66 77 } 67 78 79 /* 68 80 AutoJSIdArray::AutoJSIdArray(JSContext* cx, JSIdArray* ida) : 69 81 m_Context(cx), m_IdArray(ida) 70 82 { … … 85 97 { 86 98 if (!m_IdArray) 87 99 return 0; 88 return m_IdArray->length;100 return JS_IdArrayLength(m_Context, m_IdArray); 89 101 } 90 102 91 103 jsid AutoJSIdArray::operator[](size_t i) const … … 93 105 if (!(m_IdArray && i < (size_t)m_IdArray->length)) 94 106 return JSID_VOID; 95 107 return m_IdArray->vector[i]; 96 } 108 }*/ 109 110 111 //CRootedWrapper::CRootedWrapper(JSContext* cx, JS::Value val) 112 //{ 113 // JSAutoRequest rq(cx); 114 // JS::Value* wrap = &val; 115 // JS_WrapValue(cx, val); 116 // m_Val = boost::shared_ptr<JS::Value>(wrap, Unrooter(cx)); 117 //} -
source/scriptinterface/NativeWrapperDefns.h
79 79 #define SCRIPT_PROFILE \ 80 80 if (g_ScriptProfilingEnabled) \ 81 81 { \ 82 ENSURE( JSVAL_IS_OBJECT(JS_CALLEE(cx, vp)) && JS_ObjectIsFunction(cx, JSVAL_TO_OBJECT(JS_CALLEE(cx, vp)))); \82 ENSURE(!JSVAL_IS_PRIMITIVE(JS_CALLEE(cx, vp)) && JS_ObjectIsFunction(cx, JSVAL_TO_OBJECT(JS_CALLEE(cx, vp)))); \ 83 83 const char* name = "(unknown)"; \ 84 84 jsval nameval; \ 85 if (JS_GetReservedSlot(cx, JSVAL_TO_OBJECT(JS_CALLEE(cx, vp)), 0, &nameval)\86 &&!JSVAL_IS_VOID(nameval)) \85 nameval = JS_GetReservedSlot(JSVAL_TO_OBJECT(JS_CALLEE(cx, vp)), 0); \ 86 if (!JSVAL_IS_VOID(nameval)) \ 87 87 name = static_cast<const char*>(JSVAL_TO_PRIVATE(nameval)); \ 88 88 CProfileSampleScript profile(name); \ 89 89 } … … 91 91 // JSFastNative-compatible function that wraps the function identified in the template argument list 92 92 #define OVERLOADS(z, i, data) \ 93 93 template <typename R, TYPENAME_T0_HEAD(z,i) R (*fptr) ( ScriptInterface::CxPrivate* T0_TAIL(z,i) )> \ 94 JSBool ScriptInterface::call(JSContext* cx, uint Nargc, jsval* vp) { \94 JSBool ScriptInterface::call(JSContext* cx, uint32_t argc, jsval* vp) { \ 95 95 UNUSED2(argc); \ 96 96 SCRIPT_PROFILE \ 97 97 BOOST_PP_REPEAT_##z (i, CONVERT_ARG, ~) \ 98 98 jsval rval = JSVAL_VOID; \ 99 99 ScriptInterface_NativeWrapper<R>::call(cx, rval, fptr A0_TAIL(z,i)); \ 100 100 JS_SET_RVAL(cx, vp, rval); \ 101 return (ScriptInterface::IsExceptionPending(cx) ? JS_FALSE : JS_TRUE); \101 return !ScriptInterface::IsExceptionPending(cx); \ 102 102 } 103 103 BOOST_PP_REPEAT(SCRIPT_INTERFACE_MAX_ARGS, OVERLOADS, ~) 104 104 #undef OVERLOADS … … 106 106 // Same idea but for methods 107 107 #define OVERLOADS(z, i, data) \ 108 108 template <typename R, TYPENAME_T0_HEAD(z,i) JSClass* CLS, typename TC, R (TC::*fptr) ( T0(z,i) )> \ 109 JSBool ScriptInterface::callMethod(JSContext* cx, uint Nargc, jsval* vp) { \109 JSBool ScriptInterface::callMethod(JSContext* cx, uint32_t argc, jsval* vp) { \ 110 110 UNUSED2(argc); \ 111 111 SCRIPT_PROFILE \ 112 if (ScriptInterface::GetClass( cx, JS_THIS_OBJECT(cx, vp)) != CLS) return JS_FALSE; \113 TC* c = static_cast<TC*>(ScriptInterface::GetPrivate( cx,JS_THIS_OBJECT(cx, vp))); \114 if (! c) return JS_FALSE; \112 if (ScriptInterface::GetClass(JS_THIS_OBJECT(cx, vp)) != CLS) return false; \ 113 TC* c = static_cast<TC*>(ScriptInterface::GetPrivate(JS_THIS_OBJECT(cx, vp))); \ 114 if (! c) return false; \ 115 115 BOOST_PP_REPEAT_##z (i, CONVERT_ARG, ~) \ 116 116 jsval rval = JSVAL_VOID; \ 117 117 ScriptInterface_NativeMethodWrapper<R, TC>::call(cx, rval, c, fptr A0_TAIL(z,i)); \ 118 118 JS_SET_RVAL(cx, vp, rval); \ 119 return (ScriptInterface::IsExceptionPending(cx) ? JS_FALSE : JS_TRUE); \119 return !ScriptInterface::IsExceptionPending(cx); \ 120 120 } 121 121 BOOST_PP_REPEAT(SCRIPT_INTERFACE_MAX_ARGS, OVERLOADS, ~) 122 122 #undef OVERLOADS -
source/scriptinterface/ScriptStats.cpp
21 21 22 22 #include "scriptinterface/ScriptInterface.h" 23 23 24 #include "js/jsapi.h"25 26 24 CScriptStatsTable* g_ScriptStatsTable; 27 25 28 26 enum -
source/scriptinterface/ScriptInterface.cpp
20 20 #include "ScriptInterface.h" 21 21 // #include "DebuggingServer.h" // JS debugger temporarily disabled during the SpiderMonkey upgrade (check trac ticket #2348 for details) 22 22 #include "ScriptStats.h" 23 #include "AutoRooters.h"24 23 25 24 #include "lib/debug.h" 26 25 #include "lib/utf8.h" … … 68 67 class ScriptRuntime 69 68 { 70 69 public: 71 ScriptRuntime(int runtimeSize) : 72 m_rooter(NULL) 70 ScriptRuntime(int runtimeSize) 73 71 { 74 m_rt = JS_NewRuntime(runtimeSize); 72 // TODO: check what JS_Init() actually does and what the constraints are 73 // What I know: It must be called before calling JS_NewRuntime 74 m_rt = JS_NewRuntime(runtimeSize, JS_USE_HELPER_THREADS); 75 75 76 ENSURE(m_rt); // TODO: error handling 76 77 78 JS_SetNativeStackQuota(m_rt, 128 * sizeof(size_t) * 1024); 77 79 if (g_ScriptProfilingEnabled) 78 80 { 79 81 // Profiler isn't thread-safe, so only enable this on the main thread … … 86 88 } 87 89 } 88 90 } 91 JS_SetGCParameter(m_rt, JSGC_MAX_MALLOC_BYTES, 256 * 1024 * 1024); 92 JS_SetGCParameter(m_rt, JSGC_MAX_BYTES, 256 * 1024 * 1024); 89 93 90 JS_SetExtraGCRoots(m_rt, jshook_trace, this); 94 m_dummyContext = JS_NewContext(m_rt, STACK_CHUNK_SIZE); 95 ENSURE(m_dummyContext); 91 96 } 92 97 93 98 ~ScriptRuntime() 94 99 { 100 JS_DestroyContext(m_dummyContext); 95 101 JS_DestroyRuntime(m_rt); 96 102 } 97 103 104 JSContext* m_dummyContext; 98 105 JSRuntime* m_rt; 99 AutoGCRooter* m_rooter;100 106 101 107 private: 102 108 103 109 104 static void* jshook_script(JSContext* UNUSED(cx), JS StackFrame* UNUSED(fp), JSBool before, JSBool* UNUSED(ok), void* closure)110 static void* jshook_script(JSContext* UNUSED(cx), JSAbstractFramePtr UNUSED(fp), bool UNUSED(isConstructing), JSBool before, JSBool* UNUSED(ok), void* closure) 105 111 { 106 112 if (before) 107 113 g_Profiler.StartScript("script invocation"); … … 154 160 if (slash != filename.npos) 155 161 filename = filename.substr(slash+1); 156 162 157 uint Nline = JS_PCToLineNumber(cx, script, pc);163 uint line = JS_PCToLineNumber(cx, script, pc); 158 164 159 165 std::stringstream ss; 160 166 ss << "(" << filename << ":" << line << ")"; … … 178 184 boost::flyweights::no_locking 179 185 > LocFlyweight; 180 186 181 static void* jshook_function(JSContext* cx, JS StackFrame* fp, JSBool before, JSBool* UNUSED(ok), void* closure)187 static void* jshook_function(JSContext* cx, JSAbstractFramePtr fp, bool UNUSED(isConstructing), JSBool before, JSBool* UNUSED(ok), void* closure) 182 188 { 183 189 if (!before) 184 190 { … … 186 192 return closure; 187 193 } 188 194 189 JSFunction* fn = JS_GetFrameFunction(cx, fp);195 JSFunction* fn = fp.maybeFun(); 190 196 if (!fn) 191 197 { 192 198 g_Profiler.StartScript("(function)"); … … 207 213 } 208 214 209 215 // No name - compute from the location instead 210 ScriptLocation loc = { cx, JS_GetFrameScript(cx, fp), JS_GetFramePC(cx, fp) }; 216 JSScript* script; 217 unsigned lineno; 218 JS_DescribeScriptedCaller(cx, &script, &lineno); 219 ENSURE(script == fp.script()); 220 ScriptLocation loc = { cx, fp.script(), JS_LineNumberToPC(cx, script, lineno) }; 211 221 g_Profiler.StartScript(LocFlyweight(loc).get().name.c_str()); 212 222 213 223 return closure; 214 224 } 215 216 static void jshook_trace(JSTracer* trc, void* data)217 {218 ScriptRuntime* m = static_cast<ScriptRuntime*>(data);219 220 if (m->m_rooter)221 m->m_rooter->Trace(trc);222 }223 225 }; 224 226 225 227 shared_ptr<ScriptRuntime> ScriptInterface::CreateRuntime(int runtimeSize) … … 233 235 { 234 236 ScriptInterface_impl(const char* nativeScopeName, const shared_ptr<ScriptRuntime>& runtime); 235 237 ~ScriptInterface_impl(); 236 void Register(const char* name, JSNative fptr, uint Nnargs);238 void Register(const char* name, JSNative fptr, uint nargs); 237 239 238 240 shared_ptr<ScriptRuntime> m_runtime; 239 241 JSContext* m_cx; 240 242 JSObject* m_glob; // global scope object 243 JSCompartment* m_comp; 244 boost::rand48* m_rng; 241 245 JSObject* m_nativeScope; // native function scope object 242 246 }; 243 247 … … 246 250 247 251 JSClass global_class = { 248 252 "global", JSCLASS_GLOBAL_FLAGS, 249 JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub, 250 JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub, 251 NULL, NULL, NULL, NULL, 253 JS_PropertyStub, JS_DeletePropertyStub, 254 JS_PropertyStub, JS_StrictPropertyStub, 255 JS_EnumerateStub, JS_ResolveStub, 256 JS_ConvertStub, NULL, 252 257 NULL, NULL, NULL, NULL 253 258 }; 254 259 255 260 void ErrorReporter(JSContext* cx, const char* message, JSErrorReport* report) 256 261 { 257 // XXX Ugly hack: we want to compile code with 'use strict' and with JSOPTION_STRICT,258 // but the latter causes the former to be reported as a useless expression, so259 // ignore that specific warning here260 if (report->flags == 5 && report->lineno == 0 && report->errorNumber == 163)261 return;262 262 263 263 std::stringstream msg; 264 264 bool isWarning = JSREPORT_IS_WARNING(report->flags); … … 273 273 274 274 // If there is an exception, then print its stack trace 275 275 jsval excn; 276 if (JS_GetPendingException(cx, &excn) && JSVAL_IS_OBJECT(excn))276 if (JS_GetPendingException(cx, &excn) && !JSVAL_IS_PRIMITIVE(excn)) 277 277 { 278 278 // TODO: this violates the docs ("The error reporter callback must not reenter the JSAPI.") 279 279 … … 309 309 310 310 // Functions in the global namespace: 311 311 312 JSBool print(JSContext* cx, uint Nargc, jsval* vp)312 JSBool print(JSContext* cx, uint argc, jsval* vp) 313 313 { 314 for (uint Ni = 0; i < argc; ++i)314 for (uint i = 0; i < argc; ++i) 315 315 { 316 316 std::wstring str; 317 317 if (!ScriptInterface::FromJSVal(cx, JS_ARGV(cx, vp)[i], str)) … … 323 323 return JS_TRUE; 324 324 } 325 325 326 JSBool logmsg(JSContext* cx, uint Nargc, jsval* vp)326 JSBool logmsg(JSContext* cx, uint argc, jsval* vp) 327 327 { 328 328 if (argc < 1) 329 329 { … … 334 334 std::wstring str; 335 335 if (!ScriptInterface::FromJSVal(cx, JS_ARGV(cx, vp)[0], str)) 336 336 return JS_FALSE; 337 LOGMESSAGE(L"%ls ", str.c_str());337 LOGMESSAGE(L"%ls%f", str.c_str(), timer_Time()); 338 338 JS_SET_RVAL(cx, vp, JSVAL_VOID); 339 339 return JS_TRUE; 340 340 } 341 341 342 JSBool warn(JSContext* cx, uint Nargc, jsval* vp)342 JSBool warn(JSContext* cx, uint argc, jsval* vp) 343 343 { 344 344 if (argc < 1) 345 345 { … … 355 355 return JS_TRUE; 356 356 } 357 357 358 JSBool error(JSContext* cx, uint Nargc, jsval* vp)358 JSBool error(JSContext* cx, uint argc, jsval* vp) 359 359 { 360 360 if (argc < 1) 361 361 { … … 371 371 return JS_TRUE; 372 372 } 373 373 374 JSBool deepcopy(JSContext* cx, uint Nargc, jsval* vp)374 JSBool deepcopy(JSContext* cx, uint argc, jsval* vp) 375 375 { 376 376 if (argc < 1) 377 377 { … … 381 381 382 382 jsval ret; 383 383 384 // We'd usually do: 385 // if (!JS_StructuredClone(cx, JS_ARGV(cx, vp)[0], &ret, NULL, NULL)) 386 // return JS_FALSE; 387 // but that function is broken in the 1.8.5 release 388 // (https://bugzilla.mozilla.org/show_bug.cgi?id=651510) 389 // so do an equivalent operation with a different API: 390 JSAutoStructuredCloneBuffer buf; 391 if (!buf.write(cx, JS_ARGV(cx, vp)[0]) || !buf.read(&ret, cx)) 384 if (!JS_StructuredClone(cx, JS_ARGV(cx, vp)[0], &ret, NULL, NULL)) 392 385 return JS_FALSE; 393 386 394 387 JS_SET_RVAL(cx, vp, ret); 395 388 return JS_TRUE; 396 389 } 397 390 398 JSBool ProfileStart(JSContext* cx, uint Nargc, jsval* vp)391 JSBool ProfileStart(JSContext* cx, uint argc, jsval* vp) 399 392 { 400 393 const char* name = "(ProfileStart)"; 401 394 … … 423 416 return JS_TRUE; 424 417 } 425 418 426 JSBool ProfileStop(JSContext* UNUSED(cx), uint NUNUSED(argc), jsval* vp)419 JSBool ProfileStop(JSContext* UNUSED(cx), uint UNUSED(argc), jsval* vp) 427 420 { 428 421 if (CProfileManager::IsInitialised() && ThreadUtil::IsMainThread()) 429 422 g_Profiler.Stop(); … … 452 445 } 453 446 } 454 447 455 JSBool Math_random(JSContext* cx, uint NUNUSED(argc), jsval* vp)448 JSBool Math_random(JSContext* cx, uint UNUSED(argc), jsval* vp) 456 449 { 457 // Grab the RNG that was hidden in our slot458 jsval rngp;459 if (!JS_GetReservedSlot(cx, JSVAL_TO_OBJECT(JS_CALLEE(cx, vp)), 0, &rngp))450 double r; 451 if(!ScriptInterface::GetScriptInterfaceAndCBData(cx)->pScriptInterface->MathRandom(r)) 452 { 460 453 return JS_FALSE; 461 boost::rand48* rng = static_cast<boost::rand48*>(JSVAL_TO_PRIVATE(rngp)); 454 } 455 else 456 { 457 jsval rv = JS_NumberValue(r); 458 JS_SET_RVAL(cx, vp, rv); 459 return JS_TRUE; 460 } 461 } 462 462 463 double r = generate_uniform_real(*rng, 0.0, 1.0); 463 } // anonymous namespace 464 464 465 jsval rv; 466 if (!JS_NewNumberValue(cx, r, &rv)) 467 return JS_FALSE; 468 JS_SET_RVAL(cx, vp, rv); 469 return JS_TRUE; 465 bool ScriptInterface::MathRandom(double& nbr) 466 { 467 if (m->m_rng == NULL) 468 return false; 469 nbr = generate_uniform_real(*(m->m_rng), 0.0, 1.0); 470 return true; 470 471 } 471 472 472 } // anonymous namespace473 474 473 ScriptInterface_impl::ScriptInterface_impl(const char* nativeScopeName, const shared_ptr<ScriptRuntime>& runtime) : 475 474 m_runtime(runtime) 476 475 { 477 JSBool ok;476 bool ok; 478 477 479 478 m_cx = JS_NewContext(m_runtime->m_rt, STACK_CHUNK_SIZE); 480 479 ENSURE(m_cx); 481 480 481 JS_SetParallelCompilationEnabled(m_cx, true); 482 482 483 // For GC debugging: 483 484 // JS_SetGCZeal(m_cx, 2); 484 485 … … 486 487 487 488 JS_SetErrorReporter(m_cx, ErrorReporter); 488 489 489 uint32 options = 0; 490 options |= JSOPTION_STRICT; // "warn on dubious practice" 491 options |= JSOPTION_XML; // "ECMAScript for XML support: parse <!-- --> as a token" 490 uint32_t options = 0; 491 options |= JSOPTION_EXTRA_WARNINGS; // "warn on dubious practice" 492 // We use strict mode to encourage better coding practices and 493 //to get code that can be optimized better by Spidermonkey's JIT compiler. 494 options |= JSOPTION_STRICT_MODE; 495 //options |= JSOPTION_ALLOW_XML; // "ECMAScript for XML support: parse <!-- --> as a token" 492 496 options |= JSOPTION_VAROBJFIX; // "recommended" (fixes variable scoping) 493 497 494 498 // Enable method JIT, unless script profiling/debugging is enabled (since profiling/debugging … … 496 500 // TODO: Verify what exactly is incompatible 497 501 if (!g_ScriptProfilingEnabled && !g_JSDebuggerEnabled) 498 502 { 499 options |= JSOPTION_METHODJIT; 503 options |= JSOPTION_BASELINE; 504 options |= JSOPTION_ION; 505 options |= JSOPTION_TYPE_INFERENCE; 506 options |= JSOPTION_COMPILE_N_GO; 500 507 501 508 // Some other JIT flags to experiment with: 502 options |= JSOPTION_JIT; 503 options |= JSOPTION_PROFILING; 509 //options |= JSOPTION_METHODJIT_ALWAYS; 504 510 } 505 511 506 512 JS_SetOptions(m_cx, options); 507 JS_SetVersion(m_cx, JSVERSION_LATEST); 513 514 JSAutoRequest rq(m_cx); 515 516 JS::CompartmentOptions opt; 517 opt.setVersion(JSVERSION_LATEST); 518 m_glob = JS_NewGlobalObject(m_cx, &global_class, NULL, opt); 519 m_comp = JS_EnterCompartment(m_cx, m_glob); 520 JS_SetGlobalObject(m_cx, m_glob); 508 521 509 m_glob = JS_NewCompartmentAndGlobalObject(m_cx, &global_class, NULL);510 511 522 ok = JS_InitStandardClasses(m_cx, m_glob); 512 523 ENSURE(ok); 524 525 //JS_SetVersionForCompartment(m_comp, JSVERSION_LATEST); 513 526 527 514 528 JS_DefineProperty(m_cx, m_glob, "global", OBJECT_TO_JSVAL(m_glob), NULL, NULL, JSPROP_ENUMERATE | JSPROP_READONLY 515 529 | JSPROP_PERMANENT); 516 530 … … 529 543 530 544 ScriptInterface_impl::~ScriptInterface_impl() 531 545 { 546 { 547 JSAutoRequest rq(m_cx); 548 JS_LeaveCompartment(m_cx, m_comp); 549 } 532 550 JS_DestroyContext(m_cx); 533 551 } 534 552 535 void ScriptInterface_impl::Register(const char* name, JSNative fptr, uint Nnargs)553 void ScriptInterface_impl::Register(const char* name, JSNative fptr, uint nargs) 536 554 { 555 JSAutoRequest rq(m_cx); 537 556 JSFunction* func = JS_DefineFunction(m_cx, m_nativeScope, name, fptr, nargs, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT); 538 557 539 558 if (!func) … … 552 571 > LockedStringFlyweight; 553 572 554 573 LockedStringFlyweight fw(name); 555 JS_SetReservedSlot( m_cx,JS_GetFunctionObject(func), 0, PRIVATE_TO_JSVAL((void*)fw.get().c_str()));574 JS_SetReservedSlot(JS_GetFunctionObject(func), 0, PRIVATE_TO_JSVAL((void*)fw.get().c_str())); 556 575 } 557 576 } 558 577 … … 599 618 JS_ShutDown(); 600 619 } 601 620 621 void ScriptInterface::Tick() 622 { 623 js::NotifyAnimationActivity(m->m_glob); 624 } 625 602 626 void ScriptInterface::SetCallbackData(void* pCBData) 603 627 { 604 628 m_CxPrivate.pCBData = pCBData; … … 633 657 634 658 bool ScriptInterface::ReplaceNondeterministicRNG(boost::rand48& rng) 635 659 { 636 jsval math; 637 if (JS_GetProperty(m->m_cx, m->m_glob, "Math", &math) && JSVAL_IS_OBJECT(math)) 660 JSAutoRequest rq(m->m_cx); 661 JS::RootedValue math(m->m_cx); 662 if (JS_GetProperty(m->m_cx, m->m_glob, "Math", math.address()) && !JSVAL_IS_PRIMITIVE(math.get())) 638 663 { 639 664 JSFunction* random = JS_DefineFunction(m->m_cx, JSVAL_TO_OBJECT(math), "random", Math_random, 0, 640 665 JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT); 641 666 if (random) 642 667 { 643 // Store the RNG in a slot which is sort-of-guaranteed to be unused by the JS engine 644 if (JS_SetReservedSlot(m->m_cx, JS_GetFunctionObject(random), 0, PRIVATE_TO_JSVAL(&rng))) 645 return true; 668 m->m_rng = &rng; 669 return true; 646 670 } 647 671 } 648 672 … … 652 676 653 677 void ScriptInterface::Register(const char* name, JSNative fptr, size_t nargs) 654 678 { 655 m->Register(name, fptr, (uint N)nargs);679 m->Register(name, fptr, (uint)nargs); 656 680 } 657 681 658 682 JSContext* ScriptInterface::GetContext() const … … 670 694 return m->m_runtime; 671 695 } 672 696 673 AutoGCRooter* ScriptInterface::ReplaceAutoGCRooter(AutoGCRooter* rooter)674 {675 AutoGCRooter* ret = m->m_runtime->m_rooter;676 m->m_runtime->m_rooter = rooter;677 return ret;678 }679 697 680 681 jsval ScriptInterface::CallConstructor(jsval ctor, jsval arg) 698 jsval ScriptInterface::CallConstructor(jsval ctor, int argc, jsval argv) 682 699 { 683 if (!JSVAL_IS_OBJECT(ctor)) 700 JSAutoRequest rq(m->m_cx); 701 if (JSVAL_IS_PRIMITIVE(ctor)) 684 702 { 685 703 LOGERROR(L"CallConstructor: ctor is not an object"); 686 704 return JSVAL_VOID; 687 705 } 688 706 689 return OBJECT_TO_JSVAL(JS_New(m->m_cx, JSVAL_TO_OBJECT(ctor), 1, &arg)); 707 // Passing argc 0 and argv JSVAL_VOID causes a crash in mozjs24 708 if (argc == 0) 709 { 710 return OBJECT_TO_JSVAL(JS_New(m->m_cx, JSVAL_TO_OBJECT(ctor), 0, NULL)); 711 } 712 else 713 return OBJECT_TO_JSVAL(JS_New(m->m_cx, JSVAL_TO_OBJECT(ctor), argc, &argv)); 690 714 } 691 715 692 716 jsval ScriptInterface::NewObjectFromConstructor(jsval ctor) 693 717 { 718 JSAutoRequest rq(m->m_cx); 694 719 // Get the constructor's prototype 695 720 // (Can't use JS_GetPrototype, since we want .prototype not .__proto__) 696 jsval protoVal;697 if (!JS_GetProperty(m->m_cx, JSVAL_TO_OBJECT(ctor), "prototype", &protoVal))721 JS::RootedValue protoVal(m->m_cx); 722 if (!JS_GetProperty(m->m_cx, JSVAL_TO_OBJECT(ctor), "prototype", protoVal.address())) 698 723 { 699 724 LOGERROR(L"NewObjectFromConstructor: can't get prototype"); 700 725 return JSVAL_VOID; 701 726 } 702 727 703 if ( !JSVAL_IS_OBJECT(protoVal))728 if (JSVAL_IS_PRIMITIVE(protoVal.get())) 704 729 { 705 730 LOGERROR(L"NewObjectFromConstructor: prototype is not an object"); 706 731 return JSVAL_VOID; 707 732 } 708 733 709 JSObject* proto = JSVAL_TO_OBJECT(protoVal );710 JSObject* parent = JS_GetParent( m->m_cx,JSVAL_TO_OBJECT(ctor));734 JSObject* proto = JSVAL_TO_OBJECT(protoVal.get()); 735 JSObject* parent = JS_GetParent(JSVAL_TO_OBJECT(ctor)); 711 736 // TODO: rooting? 712 737 if (!proto || !parent) 713 738 { … … 727 752 728 753 void ScriptInterface::DefineCustomObjectType(JSClass *clasp, JSNative constructor, uint minArgs, JSPropertySpec *ps, JSFunctionSpec *fs, JSPropertySpec *static_ps, JSFunctionSpec *static_fs) 729 754 { 755 JSAutoRequest rq(m->m_cx); 730 756 std::string typeName = clasp->name; 731 757 732 758 if (m_CustomObjectTypes.find(typeName) != m_CustomObjectTypes.end()) … … 774 800 775 801 bool ScriptInterface::CallFunction_(jsval val, const char* name, size_t argc, jsval* argv, jsval& ret) 776 802 { 803 JSAutoRequest rq(m->m_cx); 777 804 JSObject* obj; 778 805 if (!JS_ValueToObject(m->m_cx, val, &obj) || obj == NULL) 779 806 return false; … … 782 809 // when calling an undefined value 783 810 JSBool found; 784 811 if (!JS_HasProperty(m->m_cx, obj, name, &found) || !found) 785 return false;812 return JS_FALSE; 786 813 787 JSBool ok = JS_CallFunctionName(m->m_cx, obj, name, (uintN)argc, argv, &ret);814 bool ok = JS_CallFunctionName(m->m_cx, obj, name, (uint)argc, argv, &ret); 788 815 789 return ok ? true : false;816 return ok ? JS_TRUE : JS_FALSE; 790 817 } 791 818 792 819 jsval ScriptInterface::GetGlobalObject() 793 820 { 794 return OBJECT_TO_JSVAL(JS_GetGlobalObject(m->m_cx)); 821 JSAutoRequest rq(m->m_cx); 822 return OBJECT_TO_JSVAL(JS_GetGlobalForScopeChain(m->m_cx)); 795 823 } 796 824 797 825 JSClass* ScriptInterface::GetGlobalClass() … … 801 829 802 830 bool ScriptInterface::SetGlobal_(const char* name, jsval value, bool replace) 803 831 { 832 JSAutoRequest rq(m->m_cx); 804 833 if (!replace) 805 834 { 806 835 JSBool found; 807 836 if (!JS_HasProperty(m->m_cx, m->m_glob, name, &found)) 808 return false;837 return JS_FALSE; 809 838 if (found) 810 839 { 811 840 JS_ReportError(m->m_cx, "SetGlobal \"%s\" called multiple times", name); 812 return false;841 return JS_FALSE; 813 842 } 814 843 } 815 844 816 JSBool ok = JS_DefineProperty(m->m_cx, m->m_glob, name, value, NULL, NULL, JSPROP_ENUMERATE | JSPROP_READONLY817 | JSPROP_PERMANENT);818 return ok ? true : false;845 bool ok = JS_DefineProperty(m->m_cx, m->m_glob, name, value, NULL, NULL, JSPROP_ENUMERATE | JSPROP_READONLY 846 | JSPROP_PERMANENT); 847 return ok ? JS_TRUE : JS_FALSE; 819 848 } 820 849 821 850 bool ScriptInterface::SetProperty_(jsval obj, const char* name, jsval value, bool constant, bool enumerate) 822 851 { 823 uintN attrs = 0; 852 JSAutoRequest rq(m->m_cx); 853 uint attrs = 0; 824 854 if (constant) 825 855 attrs |= JSPROP_READONLY | JSPROP_PERMANENT; 826 856 if (enumerate) 827 857 attrs |= JSPROP_ENUMERATE; 828 858 829 if ( ! JSVAL_IS_OBJECT(obj))859 if (JSVAL_IS_PRIMITIVE(obj)) 830 860 return false; 831 861 JSObject* object = JSVAL_TO_OBJECT(obj); 832 862 … … 837 867 838 868 bool ScriptInterface::SetProperty_(jsval obj, const wchar_t* name, jsval value, bool constant, bool enumerate) 839 869 { 840 uintN attrs = 0; 870 JSAutoRequest rq(m->m_cx); 871 uint attrs = 0; 841 872 if (constant) 842 873 attrs |= JSPROP_READONLY | JSPROP_PERMANENT; 843 874 if (enumerate) 844 875 attrs |= JSPROP_ENUMERATE; 845 876 846 if ( ! JSVAL_IS_OBJECT(obj))877 if ( JSVAL_IS_PRIMITIVE(obj)) 847 878 return false; 848 879 JSObject* object = JSVAL_TO_OBJECT(obj); 849 880 … … 855 886 856 887 bool ScriptInterface::SetPropertyInt_(jsval obj, int name, jsval value, bool constant, bool enumerate) 857 888 { 858 uintN attrs = 0; 889 JSAutoRequest rq(m->m_cx); 890 uint attrs = 0; 859 891 if (constant) 860 892 attrs |= JSPROP_READONLY | JSPROP_PERMANENT; 861 893 if (enumerate) 862 894 attrs |= JSPROP_ENUMERATE; 863 895 864 if ( ! JSVAL_IS_OBJECT(obj))896 if ( JSVAL_IS_PRIMITIVE(obj)) 865 897 return false; 866 898 JSObject* object = JSVAL_TO_OBJECT(obj); 867 899 … … 870 902 return true; 871 903 } 872 904 873 bool ScriptInterface::GetProperty_(jsval obj, const char* name, jsval&out)905 bool ScriptInterface::GetProperty_(jsval obj, const char* name, JS::MutableHandleValue out) 874 906 { 875 if (! JSVAL_IS_OBJECT(obj)) 907 JSAutoRequest rq(m->m_cx); 908 if ( JSVAL_IS_PRIMITIVE(obj)) 876 909 return false; 877 910 JSObject* object = JSVAL_TO_OBJECT(obj); 878 911 879 if (!JS_GetProperty(m->m_cx, object, name, &out))912 if (!JS_GetProperty(m->m_cx, object, name, out.address())) 880 913 return false; 881 914 return true; 882 915 } 883 916 884 bool ScriptInterface::GetPropertyInt_(jsval obj, int name, jsval&out)917 bool ScriptInterface::GetPropertyInt_(jsval obj, int name, JS::MutableHandleValue out) 885 918 { 886 if (! JSVAL_IS_OBJECT(obj)) 919 JSAutoRequest rq(m->m_cx); 920 if ( JSVAL_IS_PRIMITIVE(obj)) 887 921 return false; 888 922 JSObject* object = JSVAL_TO_OBJECT(obj); 889 923 890 if (!JS_GetPropertyById(m->m_cx, object, INT_TO_JSID(name), &out))924 if (!JS_GetPropertyById(m->m_cx, object, INT_TO_JSID(name), out.address())) 891 925 return false; 892 926 return true; 893 927 } 894 928 895 929 bool ScriptInterface::HasProperty(jsval obj, const char* name) 896 930 { 897 if (! JSVAL_IS_OBJECT(obj)) 898 return false; 931 // TODO: proper errorhandling 932 JSAutoRequest rq(m->m_cx); 933 if ( JSVAL_IS_PRIMITIVE(obj)) 934 return JS_FALSE; 899 935 JSObject* object = JSVAL_TO_OBJECT(obj); 900 936 901 937 JSBool found; 902 938 if (!JS_HasProperty(m->m_cx, object, name, &found)) 903 return false;904 return (found != JS_FALSE);939 return JS_FALSE; 940 return found; 905 941 } 906 942 907 bool ScriptInterface::EnumeratePropertyNamesWithPrefix( jsvalobj, const char* prefix, std::vector<std::string>& out)943 bool ScriptInterface::EnumeratePropertyNamesWithPrefix(JS::HandleObject obj, const char* prefix, std::vector<std::string>& out) 908 944 { 909 utf16string prefix16 (prefix, prefix+strlen(prefix)); 945 JSAutoRequest rq(m->m_cx); 946 if (obj.get() == 0x0) 947 return true; 910 948 911 if (! JSVAL_IS_OBJECT(obj))912 return false; // TODO: log error messages949 // if ( obj.get().isPrimitive() ) 950 // return false; // TODO: log error messages 913 951 914 JSObject* it = JS_NewPropertyIterator(m->m_cx, JSVAL_TO_OBJECT(obj));952 JSObject* it = JS_NewPropertyIterator(m->m_cx, obj.get()); 915 953 if (!it) 916 954 return false; 917 955 … … 927 965 continue; // ignore integer properties 928 966 929 967 JSString* name = JSVAL_TO_STRING(val); 930 size_t len; 931 const jschar* chars = JS_GetStringCharsAndLength(m->m_cx, name, &len); 932 if (chars && len >= prefix16.size() && memcmp(chars, prefix16.c_str(), prefix16.size()*2) == 0) 933 out.push_back(std::string(chars, chars+len)); // handles Unicode poorly 968 size_t len = strlen(prefix)+1; 969 char buf[len]; 970 size_t prefixLen = strlen(prefix) * sizeof(char); 971 JS_EncodeStringToBuffer(m->m_cx, name, buf, prefixLen); 972 buf[len-1]= '\0'; 973 if(0 == strcmp(buf, prefix)) 974 { 975 size_t len; 976 const jschar* chars = JS_GetStringCharsAndLength(m->m_cx, name, &len); 977 out.push_back(std::string(chars, chars+len)); 978 } 979 // if (chars && len >= prefix16.size() && memcmp(chars, prefix16.c_str(), prefix16.size()*2) == 0) 980 // out.push_back(std::string(chars, chars+len)); // handles Unicode poorly 981 934 982 } 935 983 936 984 // Recurse up the prototype chain 937 JS Object* prototype = JS_GetPrototype(m->m_cx, JSVAL_TO_OBJECT(obj));938 if ( prototype)985 JS::RootedObject prototype(m->m_cx); 986 if (JS_GetPrototype(m->m_cx, obj, prototype.address())) 939 987 { 940 if (! EnumeratePropertyNamesWithPrefix( OBJECT_TO_JSVAL(prototype), prefix, out))988 if (! EnumeratePropertyNamesWithPrefix(prototype, prefix, out)) 941 989 return false; 942 990 } 943 991 944 992 return true; 945 993 } 946 994 947 bool ScriptInterface::SetPrototype( jsval obj, jsvalproto)995 bool ScriptInterface::SetPrototype(JS::HandleObject obj, JS::HandleObject proto) 948 996 { 949 if (!JSVAL_IS_OBJECT(obj) || !JSVAL_IS_OBJECT(proto)) 950 return false; 951 return JS_SetPrototype(m->m_cx, JSVAL_TO_OBJECT(obj), JSVAL_TO_OBJECT(proto)) ? true : false; 997 JSAutoRequest rq(m->m_cx); 998 //if (JSVAL_IS_PRIMITIVE(obj) || JSVAL_IS_PRIMITIVE(proto)) 999 // return false; 1000 return JS_SetPrototype(m->m_cx, obj, proto); 952 1001 } 953 1002 954 1003 bool ScriptInterface::FreezeObject(jsval obj, bool deep) 955 1004 { 956 if (!JSVAL_IS_OBJECT(obj)) 1005 JSAutoRequest rq(m->m_cx); 1006 if (JSVAL_IS_PRIMITIVE(obj)) 957 1007 return false; 958 1008 959 1009 if (deep) … … 964 1014 965 1015 bool ScriptInterface::LoadScript(const VfsPath& filename, const std::string& code) 966 1016 { 967 // Compile the code in strict mode, to encourage better coding practices and 968 // to possibly help SpiderMonkey with optimisations 969 std::wstring codeStrict = L"\"use strict\";\n" + wstring_from_utf8(code); 970 utf16string codeUtf16(codeStrict.begin(), codeStrict.end()); 971 uintN lineNo = 0; // put the automatic 'use strict' on line 0, so the real code starts at line 1 1017 JSAutoRequest rq(m->m_cx); 1018 utf16string codeUtf16(code.begin(), code.end()); 1019 uint lineNo = 1; 972 1020 973 JSFunction* func = JS_CompileUCFunction(m->m_cx, NULL, NULL, 0, NULL, 974 reinterpret_cast<const jschar*> (codeUtf16.c_str()), (uintN)(codeUtf16.length()), 975 utf8_from_wstring(filename.string()).c_str(), lineNo); 976 1021 JS::Rooted<JSFunction*> func(m->m_cx, 1022 JS_CompileUCFunction(m->m_cx, m->m_glob, utf8_from_wstring(filename.string()).c_str(), 0, NULL, 1023 reinterpret_cast<const jschar*> (codeUtf16.c_str()), (uint)(codeUtf16.length()), 1024 utf8_from_wstring(filename.string()).c_str(), lineNo) 1025 ); 977 1026 if (!func) 978 1027 return false; 979 1028 980 jsval scriptRval;981 JSBool ok = JS_CallFunction(m->m_cx, NULL, func, 0, NULL, &scriptRval);1029 JS::RootedValue val(m->m_cx); 1030 bool ok = JS_CallFunction(m->m_cx, NULL, func, 0, NULL, val.address()); 982 1031 983 1032 return ok ? true : false; 984 1033 } 985 1034 986 1035 bool ScriptInterface::LoadGlobalScript(const VfsPath& filename, const std::wstring& code) 987 1036 { 988 // Compile the code in strict mode, to encourage better coding practices and 989 // to possibly help SpiderMonkey with optimisations 990 std::wstring codeStrict = L"\"use strict\";\n" + code; 991 utf16string codeUtf16(codeStrict.begin(), codeStrict.end()); 992 uintN lineNo = 0; // put the automatic 'use strict' on line 0, so the real code starts at line 1 1037 JSAutoRequest rq(m->m_cx); 1038 utf16string codeUtf16(code.begin(), code.end()); 1039 uint lineNo = 1; 993 1040 994 1041 jsval rval; 995 JSBool ok = JS_EvaluateUCScript(m->m_cx, m->m_glob,996 reinterpret_cast<const jschar*> (codeUtf16.c_str()), (uint N)(codeUtf16.length()),1042 bool ok = JS_EvaluateUCScript(m->m_cx, m->m_glob, 1043 reinterpret_cast<const jschar*> (codeUtf16.c_str()), (uint)(codeUtf16.length()), 997 1044 utf8_from_wstring(filename.string()).c_str(), lineNo, &rval); 998 1045 999 return ok ? true : false;1046 return ok; 1000 1047 } 1001 1048 1002 1049 bool ScriptInterface::LoadGlobalScriptFile(const VfsPath& path) 1003 1050 { 1051 JSAutoRequest rq(m->m_cx); 1004 1052 if (!VfsFileExists(path)) 1005 1053 { 1006 1054 LOGERROR(L"File '%ls' does not exist", path.string().c_str()); … … 1019 1067 1020 1068 std::wstring code = wstring_from_utf8(file.DecodeUTF8()); // assume it's UTF-8 1021 1069 1022 // Compile the code in strict mode, to encourage better coding practices and 1023 // to possibly help SpiderMonkey with optimisations 1024 std::wstring codeStrict = L"\"use strict\";\n" + code; 1025 utf16string codeUtf16(codeStrict.begin(), codeStrict.end()); 1026 uintN lineNo = 0; // put the automatic 'use strict' on line 0, so the real code starts at line 1 1070 utf16string codeUtf16(code.begin(), code.end()); 1071 uint lineNo = 1; 1027 1072 1028 1073 jsval rval; 1029 JSBool ok = JS_EvaluateUCScript(m->m_cx, m->m_glob,1030 reinterpret_cast<const jschar*> (codeUtf16.c_str()), (uint N)(codeUtf16.length()),1074 bool ok = JS_EvaluateUCScript(m->m_cx, m->m_glob, 1075 reinterpret_cast<const jschar*> (codeUtf16.c_str()), (uint)(codeUtf16.length()), 1031 1076 utf8_from_wstring(path.string()).c_str(), lineNo, &rval); 1032 1077 1033 return ok ? true : false;1078 return ok; 1034 1079 } 1035 1080 1036 1081 … … 1042 1087 1043 1088 bool ScriptInterface::Eval_(const char* code, jsval& rval) 1044 1089 { 1090 JSAutoRequest rq(m->m_cx); 1045 1091 utf16string codeUtf16(code, code+strlen(code)); 1046 1092 1047 JSBool ok = JS_EvaluateUCScript(m->m_cx, m->m_glob, (const jschar*)codeUtf16.c_str(), (uintN)codeUtf16.length(), "(eval)", 1, &rval);1048 return ok ? true : false;1093 bool ok = JS_EvaluateUCScript(m->m_cx, m->m_glob, (const jschar*)codeUtf16.c_str(), (uint)codeUtf16.length(), "(eval)", 1, &rval); 1094 return ok; 1049 1095 } 1050 1096 1051 1097 bool ScriptInterface::Eval_(const wchar_t* code, jsval& rval) 1052 1098 { 1099 JSAutoRequest rq(m->m_cx); 1053 1100 utf16string codeUtf16(code, code+wcslen(code)); 1054 1101 1055 JSBool ok = JS_EvaluateUCScript(m->m_cx, m->m_glob, (const jschar*)codeUtf16.c_str(), (uintN)codeUtf16.length(), "(eval)", 1, &rval);1056 return ok ? true : false;1102 bool ok = JS_EvaluateUCScript(m->m_cx, m->m_glob, (const jschar*)codeUtf16.c_str(), (uint)codeUtf16.length(), "(eval)", 1, &rval); 1103 return ok; 1057 1104 } 1058 1105 1059 1106 CScriptValRooted ScriptInterface::ParseJSON(const std::string& string_utf8) 1060 1107 { 1108 JSAutoRequest rq(m->m_cx); 1061 1109 std::wstring attrsW = wstring_from_utf8(string_utf8); 1062 utf16string string(attrsW.begin(), attrsW.end()); 1063 1064 jsval vp; 1065 JSONParser* parser = JS_BeginJSONParse(m->m_cx, &vp); 1066 if (!parser) 1067 { 1068 LOGERROR(L"ParseJSON failed to begin"); 1069 return CScriptValRooted(); 1070 } 1071 1072 if (!JS_ConsumeJSONText(m->m_cx, parser, reinterpret_cast<const jschar*>(string.c_str()), (uint32)string.size())) 1073 { 1074 LOGERROR(L"ParseJSON failed to consume"); 1075 return CScriptValRooted(); 1076 } 1077 1078 if (!JS_FinishJSONParse(m->m_cx, parser, JSVAL_NULL)) 1079 { 1080 LOGERROR(L"ParseJSON failed to finish"); 1081 return CScriptValRooted(); 1082 } 1083 1110 utf16string string(attrsW.begin(), attrsW.end()); 1111 JS::Rooted<jsval> vp(m->m_cx); 1112 JS_ParseJSON(m->m_cx, reinterpret_cast<const jschar*>(string.c_str()), (uint32_t)string.size(), &vp); 1084 1113 return CScriptValRooted(m->m_cx, vp); 1085 1114 } 1086 1115 … … 1109 1138 1110 1139 struct Stringifier 1111 1140 { 1112 static JSBool callback(const jschar* buf, uint32 len, void* data)1141 static JSBool callback(const jschar* buf, uint32_t len, void* data) 1113 1142 { 1114 1143 utf16string str(buf, buf+len); 1115 1144 std::wstring strw(str.begin(), str.end()); … … 1124 1153 1125 1154 struct StringifierW 1126 1155 { 1127 static JSBool callback(const jschar* buf, uint32 len, void* data)1156 static JSBool callback(const jschar* buf, uint32_t len, void* data) 1128 1157 { 1129 1158 utf16string str(buf, buf+len); 1130 1159 static_cast<StringifierW*>(data)->stream << std::wstring(str.begin(), str.end()); … … 1136 1165 1137 1166 std::string ScriptInterface::StringifyJSON(jsval obj, bool indent) 1138 1167 { 1168 JSAutoRequest rq(m->m_cx); 1139 1169 Stringifier str; 1140 1170 if (!JS_Stringify(m->m_cx, &obj, NULL, indent ? INT_TO_JSVAL(2) : JSVAL_VOID, &Stringifier::callback, &str)) 1141 1171 { … … 1151 1181 1152 1182 std::wstring ScriptInterface::ToString(jsval obj, bool pretty) 1153 1183 { 1184 JSAutoRequest rq(m->m_cx); 1154 1185 if (JSVAL_IS_VOID(obj)) 1155 1186 return L"(void 0)"; 1156 1187 … … 1163 1194 // Temporary disable the error reporter, so we don't print complaints about cyclic values 1164 1195 JSErrorReporter er = JS_SetErrorReporter(m->m_cx, NULL); 1165 1196 1166 bool ok = JS_Stringify(m->m_cx, &obj, NULL, INT_TO_JSVAL(2), &StringifierW::callback, &str) == JS_TRUE;1197 JSBool ok = JS_Stringify(m->m_cx, &obj, NULL, INT_TO_JSVAL(2), &StringifierW::callback, &str); 1167 1198 1168 1199 // Restore error reporter 1169 1200 JS_SetErrorReporter(m->m_cx, er); … … 1185 1216 1186 1217 void ScriptInterface::ReportError(const char* msg) 1187 1218 { 1219 JSAutoRequest rq(m->m_cx); 1188 1220 // JS_ReportError by itself doesn't seem to set a JS-style exception, and so 1189 1221 // script callers will be unable to catch anything. So use JS_SetPendingException 1190 1222 // to make sure there really is a script-level exception. But just set it to undefined … … 1198 1230 1199 1231 bool ScriptInterface::IsExceptionPending(JSContext* cx) 1200 1232 { 1233 JSAutoRequest rq(cx); 1201 1234 return JS_IsExceptionPending(cx) ? true : false; 1202 1235 } 1203 1236 1204 JSClass* ScriptInterface::GetClass(JS Context* cx, JSObject* obj)1237 JSClass* ScriptInterface::GetClass(JSObject* obj) 1205 1238 { 1206 UNUSED2(cx); // unused if not JS_THREADSAFE 1207 1208 return JS_GET_CLASS(cx, obj); 1239 return JS_GetClass(obj); 1209 1240 } 1210 1241 1211 void* ScriptInterface::GetPrivate(JS Context* cx, JSObject* obj)1242 void* ScriptInterface::GetPrivate(JSObject* obj) 1212 1243 { 1213 1244 // TODO: use JS_GetInstancePrivate 1214 return JS_GetPrivate( cx,obj);1245 return JS_GetPrivate(obj); 1215 1246 } 1216 1247 1217 1248 void ScriptInterface::DumpHeap() 1218 1249 { 1219 1250 #if MOZJS_DEBUG_ABI 1220 JS_DumpHeap( m->m_cx, stderr, NULL, 0, NULL, (size_t)-1, NULL);1251 JS_DumpHeap(GetJSRuntime(), stderr, NULL, JSTRACE_OBJECT, NULL, (size_t)-1, NULL); 1221 1252 #endif 1222 1253 fprintf(stderr, "# Bytes allocated: %u\n", JS_GetGCParameter(GetJSRuntime(), JSGC_BYTES)); 1223 JS_GC( m->m_cx);1254 JS_GC(GetJSRuntime()); 1224 1255 fprintf(stderr, "# Bytes allocated after GC: %u\n", JS_GetGCParameter(GetJSRuntime(), JSGC_BYTES)); 1225 1256 } 1226 1257 … … 1233 1264 { 1234 1265 public: 1235 1266 ValueCloner(ScriptInterface& from, ScriptInterface& to) : 1236 scriptInterfaceFrom(from), cxFrom(from.GetContext()), cxTo(to.GetContext()), m_RooterFrom(from ), m_RooterTo(to)1267 scriptInterfaceFrom(from), cxFrom(from.GetContext()), cxTo(to.GetContext()), m_RooterFrom(from.GetContext()), m_RooterTo(to.GetContext()) 1237 1268 { 1238 1269 } 1239 1270 … … 1247 1278 if (it != m_Mapping.end()) 1248 1279 return it->second; 1249 1280 1250 m_RooterFrom. Push(val); // root it so our mapping doesn't get invalidated1281 m_RooterFrom.append(val); // root it so our mapping doesn't get invalidated 1251 1282 1252 1283 return Clone(val); 1253 1284 } … … 1259 1290 // Clone a new value (and root it and add it to the mapping) 1260 1291 jsval Clone(jsval val) 1261 1292 { 1293 JSAutoRequest rq(cxFrom); 1262 1294 if (JSVAL_IS_DOUBLE(val)) 1263 1295 { 1264 jsval rval ;1265 CLONE_REQUIRE( JS_NewNumberValue(cxTo, JSVAL_TO_DOUBLE(val), &rval), L"JS_NewNumberValue");1266 m_RooterTo. Push(rval);1296 jsval rval = JS_NumberValue(JSVAL_TO_DOUBLE(val)); 1297 CLONE_REQUIRE(!JSVAL_IS_VOID(rval), L"JS_NumberValue"); 1298 m_RooterTo.append(rval); 1267 1299 return rval; 1268 1300 } 1269 1301 … … 1272 1304 size_t len; 1273 1305 const jschar* chars = JS_GetStringCharsAndLength(cxFrom, JSVAL_TO_STRING(val), &len); 1274 1306 CLONE_REQUIRE(chars, L"JS_GetStringCharsAndLength"); 1275 JSString* str = JS_NewUCStringCopyN(cxTo, chars, len); 1276 CLONE_REQUIRE(str, L"JS_NewUCStringCopyN"); 1277 jsval rval = STRING_TO_JSVAL(str); 1278 m_Mapping[JSVAL_TO_GCTHING(val)] = rval; 1279 m_RooterTo.Push(rval); 1280 return rval; 1307 { 1308 JSAutoRequest rq(cxTo); 1309 JSString* str = JS_NewUCStringCopyN(cxTo, chars, len); 1310 CLONE_REQUIRE(str, L"JS_NewUCStringCopyN"); 1311 jsval rval = STRING_TO_JSVAL(str); 1312 m_Mapping[JSVAL_TO_GCTHING(val)] = rval; 1313 m_RooterTo.append(rval); 1314 return rval; 1315 } 1281 1316 } 1282 1317 1283 ENSURE( JSVAL_IS_OBJECT(val));1318 ENSURE(!JSVAL_IS_PRIMITIVE(val)); 1284 1319 1285 1320 JSObject* newObj; 1286 1321 if (JS_IsArrayObject(cxFrom, JSVAL_TO_OBJECT(val))) 1287 1322 { 1288 jsuint length;1323 uint length; 1289 1324 CLONE_REQUIRE(JS_GetArrayLength(cxFrom, JSVAL_TO_OBJECT(val), &length), L"JS_GetArrayLength"); 1290 newObj = JS_NewArrayObject(cxTo, length, NULL); 1325 { 1326 JSAutoRequest rq(cxTo); 1327 newObj = JS_NewArrayObject(cxTo, length, NULL); 1328 } 1291 1329 CLONE_REQUIRE(newObj, L"JS_NewArrayObject"); 1292 1330 } 1293 1331 else 1294 1332 { 1295 newObj = JS_NewObject(cxTo, NULL, NULL, NULL); 1333 { 1334 JSAutoRequest rq(cxTo); 1335 newObj = JS_NewObject(cxTo, NULL, NULL, NULL); 1336 } 1296 1337 CLONE_REQUIRE(newObj, L"JS_NewObject"); 1297 1338 } 1298 1339 1299 1340 m_Mapping[JSVAL_TO_GCTHING(val)] = OBJECT_TO_JSVAL(newObj); 1300 m_RooterTo. Push(newObj);1341 m_RooterTo.append(OBJECT_TO_JSVAL(newObj)); 1301 1342 1302 AutoJSIdArray ida (cxFrom, JS_Enumerate(cxFrom, JSVAL_TO_OBJECT(val))); 1303 CLONE_REQUIRE(ida.get(), L"JS_Enumerate"); 1343 JS::AutoIdArray ida (cxFrom, JS_Enumerate(cxFrom, JSVAL_TO_OBJECT(val))); 1344 CLONE_REQUIRE(ida, L"JS_Enumerate"); 1345 1346 // AutoGCRooter idaRooter(scriptInterfaceFrom); 1347 // idaRooter.Push(&ida); 1304 1348 1305 AutoGCRooter idaRooter(scriptInterfaceFrom);1306 idaRooter.Push(ida.get());1307 1308 1349 for (size_t i = 0; i < ida.length(); ++i) 1309 1350 { 1310 1351 jsid id = ida[i]; 1311 jsval idval, propval; 1312 CLONE_REQUIRE(JS_IdToValue(cxFrom, id, &idval), L"JS_IdToValue"); 1313 CLONE_REQUIRE(JS_GetPropertyById(cxFrom, JSVAL_TO_OBJECT(val), id, &propval), L"JS_GetPropertyById"); 1314 jsval newPropval = GetOrClone(propval); 1352 JS::RootedValue idval(cxTo); 1353 JS::RootedValue propval(cxTo); 1354 CLONE_REQUIRE(JS_IdToValue(cxFrom, id, idval.address()), L"JS_IdToValue"); 1355 CLONE_REQUIRE(JS_GetPropertyById(cxFrom, JSVAL_TO_OBJECT(val), id, propval.address()), L"JS_GetPropertyById"); 1356 JS::RootedValue newPropval(cxTo, GetOrClone(propval)); 1315 1357 1316 1358 if (JSVAL_IS_INT(idval)) 1317 1359 { 1318 1360 // int jsids are portable across runtimes 1319 CLONE_REQUIRE(JS_SetPropertyById(cxTo, newObj, id, &newPropval), L"JS_SetPropertyById"); 1320 } 1361 JSAutoRequest rq(cxTo); 1362 CLONE_REQUIRE(JS_SetPropertyById(cxTo, newObj, id, newPropval.address()), L"JS_SetPropertyById"); 1363 } 1321 1364 else if (JSVAL_IS_STRING(idval)) 1322 1365 { 1323 1366 // string jsids are runtime-specific, so we need to copy the string content … … 1326 1369 size_t len; 1327 1370 const jschar* chars = JS_GetStringCharsAndLength(cxFrom, idstr, &len); 1328 1371 CLONE_REQUIRE(idstr, L"JS_GetStringCharsAndLength (id)"); 1329 CLONE_REQUIRE(JS_SetUCProperty(cxTo, newObj, chars, len, &newPropval), L"JS_SetUCProperty"); 1372 { 1373 JSAutoRequest rq(cxTo); 1374 CLONE_REQUIRE(JS_SetUCProperty(cxTo, newObj, chars, len, newPropval.address()), L"JS_SetUCProperty"); 1375 } 1330 1376 } 1331 1377 else 1332 1378 { … … 1341 1387 JSContext* cxFrom; 1342 1388 JSContext* cxTo; 1343 1389 std::map<void*, jsval> m_Mapping; 1344 AutoGCRooter m_RooterFrom;1345 AutoGCRooter m_RooterTo;1390 JS::AutoValueVector m_RooterFrom; 1391 JS::AutoValueVector m_RooterTo; 1346 1392 }; 1347 1393 1348 1394 jsval ScriptInterface::CloneValueFromOtherContext(ScriptInterface& otherContext, jsval val) … … 1354 1400 } 1355 1401 1356 1402 ScriptInterface::StructuredClone::StructuredClone() : 1357 m_ Context(NULL), m_Data(NULL), m_Size(0)1403 m_Data(NULL), m_Size(0) 1358 1404 { 1359 1405 } 1360 1406 1361 1407 ScriptInterface::StructuredClone::~StructuredClone() 1362 1408 { 1363 1409 if (m_Data) 1364 JS_ free(m_Context, m_Data);1410 JS_ClearStructuredClone(m_Data, m_Size); 1365 1411 } 1366 1412 1367 1413 shared_ptr<ScriptInterface::StructuredClone> ScriptInterface::WriteStructuredClone(jsval v) 1368 1414 { 1369 uint64* data = NULL; 1415 JSAutoRequest rq(m->m_cx); 1416 uint64_t* data = NULL; 1370 1417 size_t nbytes = 0; 1371 if (!JS_WriteStructuredClone(m->m_cx, v, &data, &nbytes, NULL, NULL ))1418 if (!JS_WriteStructuredClone(m->m_cx, v, &data, &nbytes, NULL, NULL, JSVAL_VOID)) 1372 1419 { 1373 1420 debug_warn(L"Writing a structured clone with JS_WriteStructuredClone failed!"); 1374 1421 return shared_ptr<StructuredClone>(); 1375 1422 } 1376 1423 1377 1424 shared_ptr<StructuredClone> ret (new StructuredClone); 1378 ret->m_Context = m->m_cx;1379 1425 ret->m_Data = data; 1380 1426 ret->m_Size = nbytes; 1381 1427 return ret; … … 1383 1429 1384 1430 jsval ScriptInterface::ReadStructuredClone(const shared_ptr<ScriptInterface::StructuredClone>& ptr) 1385 1431 { 1432 JSAutoRequest rq(m->m_cx); 1386 1433 jsval ret = JSVAL_VOID; 1387 1434 JS_ReadStructuredClone(m->m_cx, ptr->m_Data, ptr->m_Size, JS_STRUCTURED_CLONE_VERSION, &ret, NULL, NULL); 1388 1435 return ret; -
source/scriptinterface/AutoRooters.h
1 /* Copyright (C) 2010 Wildfire Games.2 * This file is part of 0 A.D.3 *4 * 0 A.D. is free software: you can redistribute it and/or modify5 * it under the terms of the GNU General Public License as published by6 * the Free Software Foundation, either version 2 of the License, or7 * (at your option) any later version.8 *9 * 0 A.D. is distributed in the hope that it will be useful,10 * but WITHOUT ANY WARRANTY; without even the implied warranty of11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12 * GNU General Public License for more details.13 *14 * You should have received a copy of the GNU General Public License15 * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.16 */17 18 #ifndef INCLUDED_AUTOROOTERS19 #define INCLUDED_AUTOROOTERS20 21 #include "scriptinterface/ScriptTypes.h"22 23 #include "js/jsapi.h"24 25 /**26 * Helper for rooting large groups of script values.27 * Construct this object, push values into it, and they will all be rooted until this28 * object is destroyed.29 * Many of these objects can be used at once, but their lifetimes must be correctly nested.30 */31 class AutoGCRooter32 {33 NONCOPYABLE(AutoGCRooter);34 public:35 AutoGCRooter(ScriptInterface& scriptInterface);36 ~AutoGCRooter();37 38 void Push(JSObject* obj) { m_Objects.push_back(obj); }39 void Push(jsval val) { m_Vals.push_back(val); }40 void Push(JSIdArray* ida) { m_IdArrays.push_back(ida); }41 42 void Trace(JSTracer* trc);43 private:44 ScriptInterface& m_ScriptInterface;45 AutoGCRooter* m_Previous;46 47 std::vector<JSObject*> m_Objects;48 std::vector<jsval> m_Vals;49 std::vector<JSIdArray*> m_IdArrays;50 // TODO: add vectors of other value types51 };52 53 #endif // INCLUDED_AUTOROOTERS -
source/scriptinterface/ScriptConversions.cpp
32 32 33 33 template<> bool ScriptInterface::FromJSVal<bool>(JSContext* cx, jsval v, bool& out) 34 34 { 35 JSAutoRequest rq(cx); 35 36 JSBool ret; 36 37 WARN_IF_NOT(JSVAL_IS_BOOLEAN(v), v); 37 38 if (!JS_ValueToBoolean(cx, v, &ret)) … … 42 43 43 44 template<> bool ScriptInterface::FromJSVal<float>(JSContext* cx, jsval v, float& out) 44 45 { 45 jsdouble ret; 46 JSAutoRequest rq(cx); 47 double ret; 46 48 WARN_IF_NOT(JSVAL_IS_NUMBER(v), v); 47 49 if (!JS_ValueToNumber(cx, v, &ret)) 48 50 return false; … … 52 54 53 55 template<> bool ScriptInterface::FromJSVal<double>(JSContext* cx, jsval v, double& out) 54 56 { 55 jsdouble ret; 57 JSAutoRequest rq(cx); 58 double ret; 56 59 WARN_IF_NOT(JSVAL_IS_NUMBER(v), v); 57 60 if (!JS_ValueToNumber(cx, v, &ret)) 58 61 return false; … … 62 65 63 66 template<> bool ScriptInterface::FromJSVal<i32>(JSContext* cx, jsval v, i32& out) 64 67 { 65 int32 ret; 68 JSAutoRequest rq(cx); 69 // TODO: Change FromJSVal to use JS::RootedValue and remove this temporary workaround here 70 JS::RootedValue v1(cx, v); 71 int32_t ret; 66 72 WARN_IF_NOT(JSVAL_IS_NUMBER(v), v); 67 if (!JS _ValueToECMAInt32(cx, v, &ret))73 if (!JS::ToInt32(cx, v1, &ret)) 68 74 return false; 69 75 out = ret; 70 76 return true; … … 72 78 73 79 template<> bool ScriptInterface::FromJSVal<u32>(JSContext* cx, jsval v, u32& out) 74 80 { 75 uint32 ret; 81 JSAutoRequest rq(cx); 82 uint32_t ret; 76 83 WARN_IF_NOT(JSVAL_IS_NUMBER(v), v); 77 84 if (!JS_ValueToECMAUint32(cx, v, &ret)) 78 85 return false; … … 82 89 83 90 template<> bool ScriptInterface::FromJSVal<u16>(JSContext* cx, jsval v, u16& out) 84 91 { 85 uint16 ret; 92 JSAutoRequest rq(cx); 93 uint16_t ret; 86 94 WARN_IF_NOT(JSVAL_IS_NUMBER(v), v); 87 95 if (!JS_ValueToUint16(cx, v, &ret)) 88 96 return false; … … 92 100 93 101 template<> bool ScriptInterface::FromJSVal<u8>(JSContext* cx, jsval v, u8& out) 94 102 { 95 uint16 ret; 103 JSAutoRequest rq(cx); 104 uint16_t ret; 96 105 WARN_IF_NOT(JSVAL_IS_NUMBER(v), v); 97 106 if (!JS_ValueToUint16(cx, v, &ret)) 98 107 return false; … … 102 111 103 112 template<> bool ScriptInterface::FromJSVal<long>(JSContext* cx, jsval v, long& out) 104 113 { 105 int32 tmp;106 JSBool ok = JS_ValueToInt32(cx, v, &tmp);114 int32_t tmp; 115 bool ok = JS_ValueToInt32(cx, v, &tmp); 107 116 out = (long)tmp; 108 return ok == JS_TRUE;117 return ok; 109 118 } 110 119 111 120 template<> bool ScriptInterface::FromJSVal<unsigned long>(JSContext* cx, jsval v, unsigned long& out) 112 121 { 113 int32 tmp;114 JSBool ok = JS_ValueToInt32(cx, v, &tmp);122 int32_t tmp; 123 bool ok = JS_ValueToInt32(cx, v, &tmp); 115 124 out = (unsigned long)tmp; 116 return ok == JS_TRUE;125 return ok; 117 126 } 118 127 119 128 // see comment below (where the same preprocessor condition is used) … … 143 152 144 153 #endif 145 154 146 // NOTE: we can't define a jsval specialisation, because that conflicts with integer types 155 template<> jsval ScriptInterface::ToJSVal<JS::Value>(JSContext* UNUSED(cx), const JS::Value& val) 156 { 157 return val; 158 } 159 147 160 template<> bool ScriptInterface::FromJSVal<CScriptVal>(JSContext* UNUSED(cx), jsval v, CScriptVal& out) 148 161 { 149 162 out = v; 150 163 return true; 151 164 } 152 165 166 template<> bool ScriptInterface::FromJSVal<JS::RootedObject>(JSContext* UNUSED(cx), jsval v, JS::RootedObject& out) 167 { 168 if (v.isObjectOrNull()) 169 { 170 out.set(JSVAL_TO_OBJECT(v)); 171 return true; 172 } 173 return false; 174 } 175 153 176 template<> bool ScriptInterface::FromJSVal<CScriptValRooted>(JSContext* cx, jsval v, CScriptValRooted& out) 154 177 { 155 178 out = CScriptValRooted(cx, v); … … 158 181 159 182 template<> bool ScriptInterface::FromJSVal<std::wstring>(JSContext* cx, jsval v, std::wstring& out) 160 183 { 184 JSAutoRequest rq(cx); 161 185 WARN_IF_NOT(JSVAL_IS_STRING(v) || JSVAL_IS_NUMBER(v), v); // allow implicit number conversions 162 186 JSString* ret = JS_ValueToString(cx, v); 163 187 if (!ret) … … 181 205 182 206 template<> bool ScriptInterface::FromJSVal<std::string>(JSContext* cx, jsval v, std::string& out) 183 207 { 208 JSAutoRequest rq(cx); 184 209 WARN_IF_NOT(JSVAL_IS_STRING(v) || JSVAL_IS_NUMBER(v), v); // allow implicit number conversions 185 210 JSString* ret = JS_ValueToString(cx, v); 186 211 if (!ret) … … 205 230 206 231 template<> bool ScriptInterface::FromJSVal<Entity>(JSContext* cx, jsval v, Entity& out) 207 232 { 233 JSAutoRequest rq(cx); 208 234 JSObject* obj; 209 235 if (!JS_ValueToObject(cx, v, &obj) || obj == NULL) 210 236 FAIL("Argument must be an object"); 211 237 212 jsval templateName, id, player, position, rotation; 238 JS::RootedValue templateName(cx); 239 JS::RootedValue id(cx); 240 JS::RootedValue player(cx); 241 JS::RootedValue position(cx); 242 JS::RootedValue rotation(cx); 213 243 214 244 // TODO: Report type errors 215 if(!JS_GetProperty(cx, obj, "player", &player) || !FromJSVal(cx, player, out.playerID))245 if(!JS_GetProperty(cx, obj, "player", player.address()) || !FromJSVal(cx, player, out.playerID)) 216 246 FAIL("Failed to read Entity.player property"); 217 if (!JS_GetProperty(cx, obj, "templateName", &templateName) || !FromJSVal(cx, templateName, out.templateName))247 if (!JS_GetProperty(cx, obj, "templateName", templateName.address()) || !FromJSVal(cx, templateName, out.templateName)) 218 248 FAIL("Failed to read Entity.templateName property"); 219 if (!JS_GetProperty(cx, obj, "id", &id) || !FromJSVal(cx, id, out.entityID))249 if (!JS_GetProperty(cx, obj, "id", id.address()) || !FromJSVal(cx, id, out.entityID)) 220 250 FAIL("Failed to read Entity.id property"); 221 if (!JS_GetProperty(cx, obj, "position", &position) || !FromJSVal(cx, position, out.position))251 if (!JS_GetProperty(cx, obj, "position", position.address()) || !FromJSVal(cx, position, out.position)) 222 252 FAIL("Failed to read Entity.position property"); 223 if (!JS_GetProperty(cx, obj, "rotation", &rotation) || !FromJSVal(cx, rotation, out.rotation))253 if (!JS_GetProperty(cx, obj, "rotation", rotation.address()) || !FromJSVal(cx, rotation, out.rotation)) 224 254 FAIL("Failed to read Entity.rotation property"); 225 255 226 256 return true; … … 234 264 return val ? JSVAL_TRUE : JSVAL_FALSE; 235 265 } 236 266 237 template<> jsval ScriptInterface::ToJSVal<float>(JSContext* cx, const float& val)267 template<> jsval ScriptInterface::ToJSVal<float>(JSContext* UNUSED(cx), const float& val) 238 268 { 239 jsval rval = JSVAL_VOID; 240 JS_NewNumberValue(cx, val, &rval); // ignore return value 269 jsval rval = JS_NumberValue(val); 241 270 return rval; 242 271 } 243 272 244 template<> jsval ScriptInterface::ToJSVal<double>(JSContext* cx, const double& val)273 template<> jsval ScriptInterface::ToJSVal<double>(JSContext* UNUSED(cx), const double& val) 245 274 { 246 jsval rval = JSVAL_VOID; 247 JS_NewNumberValue(cx, val, &rval); // ignore return value 275 jsval rval = JS_NumberValue(val); 248 276 return rval; 249 277 } 250 278 … … 264 292 return INT_TO_JSVAL(val); 265 293 } 266 294 267 template<> jsval ScriptInterface::ToJSVal<u32>(JSContext* cx, const u32& val)295 template<> jsval ScriptInterface::ToJSVal<u32>(JSContext* UNUSED(cx), const u32& val) 268 296 { 269 297 if (val <= JSVAL_INT_MAX) 270 298 return INT_TO_JSVAL(val); 271 jsval rval = JSVAL_VOID; 272 JS_NewNumberValue(cx, val, &rval); // ignore return value 299 jsval rval = JS_NumberValue(val); 273 300 return rval; 274 301 } 275 302 … … 315 342 316 343 template<> jsval ScriptInterface::ToJSVal<std::wstring>(JSContext* cx, const std::wstring& val) 317 344 { 345 JSAutoRequest rq(cx); 318 346 utf16string utf16(val.begin(), val.end()); 319 347 JSString* str = JS_NewUCStringCopyN(cx, reinterpret_cast<const jschar*> (utf16.c_str()), utf16.length()); 320 348 if (str) … … 329 357 330 358 template<> jsval ScriptInterface::ToJSVal<std::string>(JSContext* cx, const std::string& val) 331 359 { 360 JSAutoRequest rq(cx); 332 361 JSString* str = JS_NewStringCopyN(cx, val.c_str(), val.length()); 333 362 if (str) 334 363 return STRING_TO_JSVAL(str); … … 342 371 343 372 template<> jsval ScriptInterface::ToJSVal<const char*>(JSContext* cx, const char* const& val) 344 373 { 374 JSAutoRequest rq(cx); 345 375 JSString* str = JS_NewStringCopyZ(cx, val); 346 376 if (str) 347 377 return STRING_TO_JSVAL(str); … … 363 393 364 394 template<typename T> static jsval ToJSVal_vector(JSContext* cx, const std::vector<T>& val) 365 395 { 366 JSObject* obj = JS_NewArrayObject(cx, (jsint)val.size(), NULL); 396 JSAutoRequest rq(cx); 397 JSObject* obj = JS_NewArrayObject(cx, val.size(), NULL); 367 398 if (!obj) 368 399 return JSVAL_VOID; 369 for ( size_t i = 0; i < val.size(); ++i)400 for (uint32_t i = 0; i < val.size(); ++i) 370 401 { 371 jsval el = ScriptInterface::ToJSVal<T>(cx, val[i]);372 JS_SetElement(cx, obj, (jsint)i, &el);402 JS::RootedValue el(cx, ScriptInterface::ToJSVal<T>(cx, val[i])); 403 JS_SetElement(cx, obj, i, el.address()); 373 404 } 374 405 return OBJECT_TO_JSVAL(obj); 375 406 } 376 407 377 408 template<typename T> static bool FromJSVal_vector(JSContext* cx, jsval v, std::vector<T>& out) 378 409 { 410 JSAutoRequest rq(cx); 379 411 JSObject* obj; 380 if (!JS_ValueToObject(cx, v, &obj) || obj == NULL || !(JS_IsArrayObject(cx, obj) || js_IsTypedArray(obj)))412 if (!JS_ValueToObject(cx, v, &obj) || obj == NULL || !(JS_IsArrayObject(cx, obj) || JS_IsTypedArrayObject(obj))) 381 413 FAIL("Argument must be an array"); 382 jsuint length;414 uint32_t length; 383 415 if (!JS_GetArrayLength(cx, obj, &length)) 384 416 FAIL("Failed to get array length"); 385 417 out.reserve(length); 386 for ( jsuint i = 0; i < length; ++i)418 for (uint32_t i = 0; i < length; ++i) 387 419 { 388 jsval el;389 if (!JS_GetElement(cx, obj, i, &el))420 JS::RootedValue el(cx); 421 if (!JS_GetElement(cx, obj, i, el.address())) 390 422 FAIL("Failed to read array element"); 391 423 T el2; 392 424 if (!ScriptInterface::FromJSVal<T>(cx, el, el2)) -
source/scripting/JSUtil.cpp
1 /* Copyright (C) 2009 Wildfire Games.2 * This file is part of 0 A.D.3 *4 * 0 A.D. is free software: you can redistribute it and/or modify5 * it under the terms of the GNU General Public License as published by6 * the Free Software Foundation, either version 2 of the License, or7 * (at your option) any later version.8 *9 * 0 A.D. is distributed in the hope that it will be useful,10 * but WITHOUT ANY WARRANTY; without even the implied warranty of11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12 * GNU General Public License for more details.13 *14 * You should have received a copy of the GNU General Public License15 * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.16 */17 18 #include "precompiled.h"19 20 #include "SpiderMonkey.h"21 22 JSBool jsu_report_param_error(JSContext* cx, jsval* vp)23 {24 JS_ReportError(cx, "Invalid parameter(s) or count");25 26 if (vp)27 JS_SET_RVAL(cx, vp, JSVAL_NULL);28 29 // yes, we had an error, but returning JS_FALSE would cause SpiderMonkey30 // to abort. that would be hard to debug.31 return JS_TRUE;32 } -
source/scripting/SpiderMonkey.h
35 35 36 36 #include "scriptinterface/ScriptTypes.h" 37 37 38 #include "JSUtil.h"39 40 38 // Make JS debugging a little easier by automatically naming GC roots 41 39 // Don't simply #define NAME_ALL_GC_ROOTS, because jsapi.h is horridly broken 42 40 #ifndef NDEBUG -
source/scripting/JSUtil.h
1 /* Copyright (C) 2009 Wildfire Games.2 * This file is part of 0 A.D.3 *4 * 0 A.D. is free software: you can redistribute it and/or modify5 * it under the terms of the GNU General Public License as published by6 * the Free Software Foundation, either version 2 of the License, or7 * (at your option) any later version.8 *9 * 0 A.D. is distributed in the hope that it will be useful,10 * but WITHOUT ANY WARRANTY; without even the implied warranty of11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12 * GNU General Public License for more details.13 *14 * You should have received a copy of the GNU General Public License15 * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.16 */17 18 // included from SpiderMonkey.h19 20 extern JSBool jsu_report_param_error(JSContext* cx, jsval* vp);21 22 23 // consistent argc checking for normal function wrappers: reports an24 // error via JS and returns if number of parameters is incorrect.25 // .. require exact number (most common case)26 #define JSU_REQUIRE_PARAMS(exact_number)\27 if(argc != exact_number)\28 return jsu_report_param_error(cx, vp);29 // .. require 0 params (avoids L4 warning "unused argv param")30 #define JSU_REQUIRE_NO_PARAMS()\31 if(argc != 0)\32 return jsu_report_param_error(cx, vp);33 // .. require a certain range (e.g. due to optional params)34 #define JSU_REQUIRE_PARAM_RANGE(min_number, max_number)\35 if(!(min_number <= argc && argc <= max_number))\36 return jsu_report_param_error(cx, vp);37 // .. require at most a certain count38 #define JSU_REQUIRE_MAX_PARAMS(max_number)\39 if(argc > max_number)\40 return jsu_report_param_error(cx, vp);41 // .. require at least a certain count (rarely needed)42 #define JSU_REQUIRE_MIN_PARAMS(min_number)\43 if(argc < min_number)\44 return jsu_report_param_error(cx, vp);45 46 // same as JSU_REQUIRE_PARAMS, but used from C++ functions that are47 // a bit further removed from SpiderMonkey, i.e. return a48 // C++ bool indicating success, and not taking an rval param.49 #define JSU_REQUIRE_PARAMS_CPP(exact_number)\50 if(argc != exact_number)\51 {\52 jsu_report_param_error(cx, 0);\53 return false;\54 }55 56 57 #define JSU_ASSERT(expr, msg)\58 STMT(\59 if(!(expr))\60 {\61 JS_ReportError(cx, msg);\62 return JS_FALSE;\63 }\64 ) -
source/lib/types.h
33 33 34 34 #define i8 int8_t 35 35 #define i16 int16_t 36 #define i32 int32_t 36 //#define i32 int32_t 37 typedef int32_t i32; 37 38 #define i64 int64_t 38 39 39 40 #define u8 uint8_t 40 #define u16 uint16_t 41 #define u32 uint32_t 41 //#define u16 uint16_t 42 typedef uint16_t u16; 43 //#define u32 uint32_t 44 typedef uint32_t u32; 42 45 #define u64 uint64_t 43 46 44 47 #endif // #ifndef INCLUDED_TYPES -
source/gui/IGUIObject.cpp
420 420 throw PSERROR_GUI_OperationNeedsGUIObject(); 421 421 422 422 JSContext* cx = pGUI->GetScriptInterface()->GetContext(); 423 JSAutoRequest rq(cx); 423 424 424 425 const int paramCount = 1; 425 426 const char* paramNames[paramCount] = { "mouse" }; … … 467 468 return; 468 469 469 470 JSContext* cx = m_pGUI->GetScriptInterface()->GetContext(); 470 471 JSAutoRequest rq(cx); 472 471 473 // Set up the 'mouse' parameter 472 474 CScriptVal mouse; 473 475 m_pGUI->GetScriptInterface()->Eval("({})", mouse); … … 478 480 jsval paramData[] = { mouse.get() }; 479 481 480 482 jsval result; 481 JSBool ok = JS_CallFunctionValue(cx, GetJSObject(), (*it).second.get(), ARRAY_SIZE(paramData), paramData, &result);483 bool ok = JS_CallFunctionValue(cx, GetJSObject(), (*it).second.get(), ARRAY_SIZE(paramData), paramData, &result); 482 484 if (!ok) 483 485 { 484 486 // We have no way to propagate the script exception, so just ignore it … … 498 500 jsval arg = Argument.get(); 499 501 500 502 jsval result; 501 JSBool ok = JS_CallFunctionValue(cx, object, (*it).second.get(), 1, &arg, &result);503 bool ok = JS_CallFunctionValue(cx, object, (*it).second.get(), 1, &arg, &result); 502 504 if (!ok) 503 505 { 504 506 JS_ReportError(cx, "Errors executing script action \"%s\"", Action.c_str()); … … 508 510 JSObject* IGUIObject::GetJSObject() 509 511 { 510 512 JSContext* cx = m_pGUI->GetScriptInterface()->GetContext(); 513 JSAutoRequest rq(cx); 511 514 // Cache the object when somebody first asks for it, because otherwise 512 515 // we end up doing far too much object allocation. TODO: Would be nice to 513 516 // not have these objects hang around forever using up memory, though. … … 515 518 { 516 519 JSObject* obj = JS_NewObject(cx, &JSI_IGUIObject::JSI_class, NULL, NULL); 517 520 m_JSObject = CScriptValRooted(cx, OBJECT_TO_JSVAL(obj)); 518 JS_SetPrivate( cx,JSVAL_TO_OBJECT(m_JSObject.get()), this);521 JS_SetPrivate(JSVAL_TO_OBJECT(m_JSObject.get()), this); 519 522 } 520 523 return JSVAL_TO_OBJECT(m_JSObject.get());; 521 524 } -
source/gui/scripting/JSInterface_GUITypes.cpp
23 23 /**** GUISize ****/ 24 24 JSClass JSI_GUISize::JSI_class = { 25 25 "GUISize", 0, 26 JS_PropertyStub, JS_ PropertyStub,26 JS_PropertyStub, JS_DeletePropertyStub, 27 27 JS_PropertyStub, JS_StrictPropertyStub, 28 28 JS_EnumerateStub, JS_ResolveStub, 29 JS_ConvertStub, JS_FinalizeStub,29 JS_ConvertStub, NULL, 30 30 NULL, NULL, NULL, JSI_GUISize::construct 31 31 }; 32 32 … … 45 45 46 46 JSFunctionSpec JSI_GUISize::JSI_methods[] = 47 47 { 48 { "toString", JSI_GUISize::toString, 0, 0 },49 { 0 }48 JS_FS("toString", JSI_GUISize::toString, 0, 0), 49 JS_FS_END 50 50 }; 51 51 52 JSBool JSI_GUISize::construct(JSContext* cx, uint Nargc, jsval* vp)52 JSBool JSI_GUISize::construct(JSContext* cx, uint argc, jsval* vp) 53 53 { 54 54 JSObject* obj = JS_NewObject(cx, &JSI_GUISize::JSI_class, NULL, NULL); 55 55 56 // TODO: ugly with so much repetition...? 56 57 if (argc == 8) 57 58 { 58 JS_SetProperty(cx, obj, "left", &JS_ARGV(cx, vp)[0]); 59 JS_SetProperty(cx, obj, "top", &JS_ARGV(cx, vp)[1]); 60 JS_SetProperty(cx, obj, "right", &JS_ARGV(cx, vp)[2]); 61 JS_SetProperty(cx, obj, "bottom", &JS_ARGV(cx, vp)[3]); 62 JS_SetProperty(cx, obj, "rleft", &JS_ARGV(cx, vp)[4]); 63 JS_SetProperty(cx, obj, "rtop", &JS_ARGV(cx, vp)[5]); 64 JS_SetProperty(cx, obj, "rright", &JS_ARGV(cx, vp)[6]); 65 JS_SetProperty(cx, obj, "rbottom", &JS_ARGV(cx, vp)[7]); 59 JS::RootedValue v0(cx, JS_ARGV(cx, vp)[0]); 60 JS::RootedValue v1(cx, JS_ARGV(cx, vp)[1]); 61 JS::RootedValue v2(cx, JS_ARGV(cx, vp)[2]); 62 JS::RootedValue v3(cx, JS_ARGV(cx, vp)[3]); 63 JS::RootedValue v4(cx, JS_ARGV(cx, vp)[4]); 64 JS::RootedValue v5(cx, JS_ARGV(cx, vp)[5]); 65 JS::RootedValue v6(cx, JS_ARGV(cx, vp)[6]); 66 JS::RootedValue v7(cx, JS_ARGV(cx, vp)[7]); 67 JS_SetProperty(cx, obj, "left", v0.address()); 68 JS_SetProperty(cx, obj, "top", v1.address()); 69 JS_SetProperty(cx, obj, "right", v2.address()); 70 JS_SetProperty(cx, obj, "bottom", v3.address()); 71 JS_SetProperty(cx, obj, "rleft", v4.address()); 72 JS_SetProperty(cx, obj, "rtop", v5.address()); 73 JS_SetProperty(cx, obj, "rright", v6.address()); 74 JS_SetProperty(cx, obj, "rbottom", v7.address()); 66 75 } 67 76 else if (argc == 4) 68 77 { 69 jsval zero = JSVAL_ZERO; 70 JS_SetProperty(cx, obj, "left", &JS_ARGV(cx, vp)[0]); 71 JS_SetProperty(cx, obj, "top", &JS_ARGV(cx, vp)[1]); 72 JS_SetProperty(cx, obj, "right", &JS_ARGV(cx, vp)[2]); 73 JS_SetProperty(cx, obj, "bottom", &JS_ARGV(cx, vp)[3]); 74 JS_SetProperty(cx, obj, "rleft", &zero); 75 JS_SetProperty(cx, obj, "rtop", &zero); 76 JS_SetProperty(cx, obj, "rright", &zero); 77 JS_SetProperty(cx, obj, "rbottom", &zero); 78 JS::RootedValue zero(cx, JSVAL_ZERO); 79 JS::RootedValue v0(cx, JS_ARGV(cx, vp)[0]); 80 JS::RootedValue v1(cx, JS_ARGV(cx, vp)[1]); 81 JS::RootedValue v2(cx, JS_ARGV(cx, vp)[2]); 82 JS::RootedValue v3(cx, JS_ARGV(cx, vp)[3]); 83 JS_SetProperty(cx, obj, "left", v0.address()); 84 JS_SetProperty(cx, obj, "top", v1.address()); 85 JS_SetProperty(cx, obj, "right", v2.address()); 86 JS_SetProperty(cx, obj, "bottom", v3.address()); 87 JS_SetProperty(cx, obj, "rleft", zero.address()); 88 JS_SetProperty(cx, obj, "rtop", zero.address()); 89 JS_SetProperty(cx, obj, "rright", zero.address()); 90 JS_SetProperty(cx, obj, "rbottom", zero.address()); 78 91 } 79 92 else 80 93 { 81 jsval zero = JSVAL_ZERO;82 JS_SetProperty(cx, obj, "left", &zero);83 JS_SetProperty(cx, obj, "top", &zero);84 JS_SetProperty(cx, obj, "right", &zero);85 JS_SetProperty(cx, obj, "bottom", &zero);86 JS_SetProperty(cx, obj, "rleft", &zero);87 JS_SetProperty(cx, obj, "rtop", &zero);88 JS_SetProperty(cx, obj, "rright", &zero);89 JS_SetProperty(cx, obj, "rbottom", &zero);94 JS::RootedValue zero(cx, JSVAL_ZERO); 95 JS_SetProperty(cx, obj, "left", zero.address()); 96 JS_SetProperty(cx, obj, "top", zero.address()); 97 JS_SetProperty(cx, obj, "right", zero.address()); 98 JS_SetProperty(cx, obj, "bottom", zero.address()); 99 JS_SetProperty(cx, obj, "rleft", zero.address()); 100 JS_SetProperty(cx, obj, "rtop", zero.address()); 101 JS_SetProperty(cx, obj, "rright", zero.address()); 102 JS_SetProperty(cx, obj, "rbottom", zero.address()); 90 103 } 91 104 92 105 JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(obj)); … … 102 115 return CStr::FromDouble(per)+"%"+( pix == 0.0 ? CStr() : pix > 0.0 ? CStr("+")+CStr::FromDouble(pix) : CStr::FromDouble(pix) ); 103 116 } 104 117 105 JSBool JSI_GUISize::toString(JSContext* cx, uint Nargc, jsval* vp)118 JSBool JSI_GUISize::toString(JSContext* cx, uint argc, jsval* vp) 106 119 { 107 120 UNUSED2(argc); 108 121 … … 141 154 142 155 JSClass JSI_GUIColor::JSI_class = { 143 156 "GUIColor", 0, 144 JS_PropertyStub, JS_ PropertyStub,157 JS_PropertyStub, JS_DeletePropertyStub, 145 158 JS_PropertyStub, JS_StrictPropertyStub, 146 159 JS_EnumerateStub, JS_ResolveStub, 147 JS_ConvertStub, JS_FinalizeStub,160 JS_ConvertStub, NULL, 148 161 NULL, NULL, NULL, JSI_GUIColor::construct 149 162 }; 150 163 … … 159 172 160 173 JSFunctionSpec JSI_GUIColor::JSI_methods[] = 161 174 { 162 { "toString", JSI_GUIColor::toString, 0, 0 },163 { 0 }175 JS_FS("toString", JSI_GUIColor::toString, 0, 0), 176 JS_FS_END 164 177 }; 165 178 166 JSBool JSI_GUIColor::construct(JSContext* cx, uint Nargc, jsval* vp)179 JSBool JSI_GUIColor::construct(JSContext* cx, uint argc, jsval* vp) 167 180 { 168 181 JSObject* obj = JS_NewObject(cx, &JSI_GUIColor::JSI_class, NULL, NULL); 169 182 … … 177 190 else 178 191 { 179 192 // Nice magenta: 180 jsval c;181 if ( !JS_NewNumberValue(cx, 1.0, &c))193 JS::RootedValue c(cx, JS_NumberValue(1.0)); 194 if (JSVAL_IS_NULL(c)) 182 195 return JS_FALSE; 183 JS_SetProperty(cx, obj, "r", &c); 184 JS_SetProperty(cx, obj, "b", &c); 185 JS_SetProperty(cx, obj, "a", &c); 186 if (!JS_NewNumberValue(cx, 0.0, &c)) 196 JS_SetProperty(cx, obj, "r", c.address()); 197 JS_SetProperty(cx, obj, "b", c.address()); 198 JS_SetProperty(cx, obj, "a", c.address()); 199 c = JS_NumberValue(0.0); 200 if (JSVAL_IS_NULL(c)) 187 201 return JS_FALSE; 188 JS_SetProperty(cx, obj, "g", &c);202 JS_SetProperty(cx, obj, "g", c.address()); 189 203 } 190 204 191 205 JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(obj)); 192 206 return JS_TRUE; 193 207 } 194 208 195 JSBool JSI_GUIColor::toString(JSContext* cx, uint Nargc, jsval* vp)209 JSBool JSI_GUIColor::toString(JSContext* cx, uint argc, jsval* vp) 196 210 { 197 211 UNUSED2(argc); 198 212 … … 218 232 219 233 JSClass JSI_GUIMouse::JSI_class = { 220 234 "GUIMouse", 0, 221 JS_PropertyStub, JS_ PropertyStub,235 JS_PropertyStub, JS_DeletePropertyStub, 222 236 JS_PropertyStub, JS_StrictPropertyStub, 223 237 JS_EnumerateStub, JS_ResolveStub, 224 JS_ConvertStub, JS_FinalizeStub,238 JS_ConvertStub, NULL, 225 239 NULL, NULL, NULL, JSI_GUIMouse::construct 226 240 }; 227 241 … … 235 249 236 250 JSFunctionSpec JSI_GUIMouse::JSI_methods[] = 237 251 { 238 { "toString", JSI_GUIMouse::toString, 0, 0 },239 { 0 }252 JS_FS("toString", JSI_GUIMouse::toString, 0, 0), 253 JS_FS_END 240 254 }; 241 255 242 JSBool JSI_GUIMouse::construct(JSContext* cx, uint Nargc, jsval* vp)256 JSBool JSI_GUIMouse::construct(JSContext* cx, uint argc, jsval* vp) 243 257 { 244 258 JSObject* obj = JS_NewObject(cx, &JSI_GUIMouse::JSI_class, NULL, NULL); 245 259 246 260 if (argc == 3) 247 261 { 248 JS_SetProperty(cx, obj, "x", &JS_ARGV(cx, vp)[0]); 249 JS_SetProperty(cx, obj, "y", &JS_ARGV(cx, vp)[1]); 250 JS_SetProperty(cx, obj, "buttons", &JS_ARGV(cx, vp)[2]); 262 JS::RootedValue v0(cx, JS_ARGV(cx, vp)[0]); 263 JS::RootedValue v1(cx, JS_ARGV(cx, vp)[1]); 264 JS::RootedValue v2(cx, JS_ARGV(cx, vp)[2]); 265 JS_SetProperty(cx, obj, "x", v0.address()); 266 JS_SetProperty(cx, obj, "y", v1.address()); 267 JS_SetProperty(cx, obj, "buttons", v2.address()); 251 268 } 252 269 else 253 270 { 254 jsval zero = JSVAL_ZERO;255 JS_SetProperty(cx, obj, "x", &zero);256 JS_SetProperty(cx, obj, "y", &zero);257 JS_SetProperty(cx, obj, "buttons", &zero);271 JS::RootedValue zero (cx, JSVAL_ZERO); 272 JS_SetProperty(cx, obj, "x", zero.address()); 273 JS_SetProperty(cx, obj, "y", zero.address()); 274 JS_SetProperty(cx, obj, "buttons", zero.address()); 258 275 } 259 276 260 277 JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(obj)); 261 278 return JS_TRUE; 262 279 } 263 280 264 JSBool JSI_GUIMouse::toString(JSContext* cx, uint Nargc, jsval* vp)281 JSBool JSI_GUIMouse::toString(JSContext* cx, uint argc, jsval* vp) 265 282 { 266 283 UNUSED2(argc); 267 284 268 int32 x, y, buttons;285 int32_t x, y, buttons; 269 286 ScriptInterface* pScriptInterface = ScriptInterface::GetScriptInterfaceAndCBData(cx)->pScriptInterface; 270 287 pScriptInterface->GetProperty(JS_THIS_VALUE(cx, vp), "x", x); 271 288 pScriptInterface->GetProperty(JS_THIS_VALUE(cx, vp), "y", y); -
source/gui/scripting/JSInterface_GUITypes.h
26 26 extern JSClass JSI_class; \ 27 27 extern JSPropertySpec JSI_props[]; \ 28 28 extern JSFunctionSpec JSI_methods[]; \ 29 JSBool construct(JSContext* cx, uint Nargc, jsval* vp); \30 JSBool toString(JSContext* cx, uint Nargc, jsval* vp); \29 JSBool construct(JSContext* cx, uint argc, jsval* vp); \ 30 JSBool toString(JSContext* cx, uint argc, jsval* vp); \ 31 31 } 32 32 33 33 GUISTDTYPE(Size) -
source/gui/scripting/ScriptFunctions.cpp
69 69 #include "soundmanager/SoundManager.h" 70 70 #include "soundmanager/scripting/JSInterface_Sound.h" 71 71 72 #include "js/jsapi.h"73 72 /* 74 73 * This file defines a set of functions that are available to GUI scripts, to allow 75 74 * interaction with the rest of the engine. … … 552 551 void ForceGC(ScriptInterface::CxPrivate* pCxPrivate) 553 552 { 554 553 double time = timer_Time(); 555 JS_GC(pCxPrivate->pScriptInterface->Get Context());554 JS_GC(pCxPrivate->pScriptInterface->GetJSRuntime()); 556 555 time = timer_Time() - time; 557 556 g_Console->InsertMessage(L"Garbage collection completed in: %f", time); 558 557 } -
source/gui/scripting/JSInterface_IGUIObject.cpp
32 32 33 33 JSClass JSI_IGUIObject::JSI_class = { 34 34 "GUIObject", JSCLASS_HAS_PRIVATE, 35 JS_PropertyStub, JS_ PropertyStub,35 JS_PropertyStub, JS_DeletePropertyStub, 36 36 JSI_IGUIObject::getProperty, JSI_IGUIObject::setProperty, 37 37 JS_EnumerateStub, JS_ResolveStub, 38 JS_ConvertStub, JS_FinalizeStub,38 JS_ConvertStub, NULL, 39 39 NULL, NULL, NULL, JSI_IGUIObject::construct 40 40 }; 41 41 42 JSPropertySpec JSI_IGUIObject::JSI_props[] = 42 JSPropertySpec JSI_IGUIObject::JSI_props[] = 43 43 { 44 44 { 0 } 45 45 }; 46 46 47 JSFunctionSpec JSI_IGUIObject::JSI_methods[] = 47 JSFunctionSpec JSI_IGUIObject::JSI_methods[] = 48 48 { 49 { "toString", JSI_IGUIObject::toString, 0, 0 },50 { "focus", JSI_IGUIObject::focus, 0, 0 },51 { "blur", JSI_IGUIObject::blur, 0, 0 },52 { "getComputedSize", JSI_IGUIObject::getComputedSize, 0, 0 },53 { 0 }49 JS_FS("toString", JSI_IGUIObject::toString, 0, 0), 50 JS_FS("focus", JSI_IGUIObject::focus, 0, 0), 51 JS_FS("blur", JSI_IGUIObject::blur, 0, 0), 52 JS_FS("getComputedSize", JSI_IGUIObject::getComputedSize, 0, 0), 53 JS_FS_END 54 54 }; 55 55 56 JSBool JSI_IGUIObject::getProperty(JSContext* cx, JS Object* obj, jsid id, jsval*vp)56 JSBool JSI_IGUIObject::getProperty(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JS::MutableHandle<jsval> vp) 57 57 { 58 58 IGUIObject* e = (IGUIObject*)JS_GetInstancePrivate(cx, obj, &JSI_IGUIObject::JSI_class, NULL); 59 59 if (!e) … … 88 88 CStr eventName (CStr(propName.substr(2)).LowerCase()); 89 89 std::map<CStr, CScriptValRooted>::iterator it = e->m_ScriptHandlers.find(eventName); 90 90 if (it == e->m_ScriptHandlers.end()) 91 *vp = JSVAL_NULL;91 vp.set(JSVAL_NULL); 92 92 else 93 *vp = it->second.get();93 vp.set((*it).second.get()); 94 94 return JS_TRUE; 95 95 } 96 96 … … 102 102 if (parent) 103 103 { 104 104 // If the object isn't parentless, return a new object 105 *vp = OBJECT_TO_JSVAL(parent->GetJSObject());105 vp.set(OBJECT_TO_JSVAL(parent->GetJSObject())); 106 106 } 107 107 else 108 108 { 109 109 // Return null if there's no parent 110 *vp = JSVAL_NULL;110 vp.set(JSVAL_NULL); 111 111 } 112 112 return JS_TRUE; 113 113 } 114 114 // Also handle "name" specially 115 115 else if (propName == "name") 116 116 { 117 *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, e->GetName().c_str()));117 vp.set(STRING_TO_JSVAL(JS_NewStringCopyZ(cx, e->GetName().c_str()))); 118 118 return JS_TRUE; 119 119 } 120 120 // Handle all other properties … … 135 135 { 136 136 bool value; 137 137 GUI<bool>::GetSetting(e, propName, value); 138 *vp = value ? JSVAL_TRUE : JSVAL_FALSE; 138 vp.set(BOOLEAN_TO_JSVAL(value)); 139 //value ? JSVAL_TRUE : JSVAL_FALSE; 139 140 break; 140 141 } 141 142 … … 143 144 { 144 145 int value; 145 146 GUI<int>::GetSetting(e, propName, value); 146 *vp = INT_TO_JSVAL(value);147 vp.set(INT_TO_JSVAL(value)); 147 148 break; 148 149 } 149 150 … … 152 153 float value; 153 154 GUI<float>::GetSetting(e, propName, value); 154 155 // Create a garbage-collectable double 155 return JS_NewNumberValue(cx, value, vp); 156 vp.set(JS_NumberValue(value)); 157 return !JSVAL_IS_NULL(vp.get()); 156 158 } 157 159 158 160 case GUIST_CColor: … … 160 162 CColor colour; 161 163 GUI<CColor>::GetSetting(e, propName, colour); 162 164 JSObject* obj = JS_NewObject(cx, &JSI_GUIColor::JSI_class, NULL, NULL); 163 *vp = OBJECT_TO_JSVAL(obj); // root it165 vp.set(OBJECT_TO_JSVAL(obj)); // root it 164 166 165 jsval c;167 JS::RootedValue c(cx); 166 168 // Attempt to minimise ugliness through macrosity 167 #define P(x) if (!JS_NewNumberValue(cx, colour.x, &c)) return JS_FALSE; JS_SetProperty(cx, obj, #x, &c) 169 #define P(x) c = JS_NumberValue(colour.x); \ 170 if (JSVAL_IS_NULL(c)) return false; JS_SetProperty(cx, obj, #x, c.address()) 168 171 P(r); 169 172 P(g); 170 173 P(b); … … 179 182 CClientArea area; 180 183 GUI<CClientArea>::GetSetting(e, propName, area); 181 184 JSObject* obj = JS_NewObject(cx, &JSI_GUISize::JSI_class, NULL, NULL); 182 *vp = OBJECT_TO_JSVAL(obj); // root it185 vp.set(OBJECT_TO_JSVAL(obj)); // root it 183 186 try 184 187 { 185 188 ScriptInterface* pScriptInterface = ScriptInterface::GetScriptInterfaceAndCBData(cx)->pScriptInterface; … … 207 210 { 208 211 CGUIString value; 209 212 GUI<CGUIString>::GetSetting(e, propName, value); 210 *vp = ScriptInterface::ToJSVal(cx, value.GetOriginalString());213 vp.set(ScriptInterface::ToJSVal(cx, value.GetOriginalString())); 211 214 break; 212 215 } 213 216 … … 215 218 { 216 219 CStr value; 217 220 GUI<CStr>::GetSetting(e, propName, value); 218 *vp = ScriptInterface::ToJSVal(cx, value);221 vp.set(ScriptInterface::ToJSVal(cx, value)); 219 222 break; 220 223 } 221 224 … … 223 226 { 224 227 CStrW value; 225 228 GUI<CStrW>::GetSetting(e, propName, value); 226 *vp = ScriptInterface::ToJSVal(cx, value);229 vp.set(ScriptInterface::ToJSVal(cx, value)); 227 230 break; 228 231 } 229 232 … … 231 234 { 232 235 CGUISpriteInstance *value; 233 236 GUI<CGUISpriteInstance>::GetSettingPointer(e, propName, value); 234 *vp = ScriptInterface::ToJSVal(cx, value->GetName());237 vp.set(ScriptInterface::ToJSVal(cx, value->GetName())); 235 238 break; 236 239 } 237 240 … … 247 250 case EAlign_Center: word = "center"; break; 248 251 default: debug_warn(L"Invalid EAlign!"); word = "error"; break; 249 252 } 250 *vp = ScriptInterface::ToJSVal(cx, word);253 vp.set(ScriptInterface::ToJSVal(cx, word)); 251 254 break; 252 255 } 253 256 … … 263 266 case EVAlign_Center: word = "center"; break; 264 267 default: debug_warn(L"Invalid EVAlign!"); word = "error"; break; 265 268 } 266 *vp = ScriptInterface::ToJSVal(cx, word);269 vp.set(ScriptInterface::ToJSVal(cx, word)); 267 270 break; 268 271 } 269 272 … … 273 276 GUI<CGUIList>::GetSetting(e, propName, value); 274 277 275 278 JSObject *obj = JS_NewArrayObject(cx, 0, NULL); 276 *vp = OBJECT_TO_JSVAL(obj); // root it277 279 vp.set(OBJECT_TO_JSVAL(obj)); // root it 280 278 281 for (size_t i = 0; i < value.m_Items.size(); ++i) 279 282 { 280 jsval val = ScriptInterface::ToJSVal(cx, value.m_Items[i].GetOriginalString());281 JS_SetElement(cx, obj, ( jsint)i, &val);283 JS::RootedValue val(cx, ScriptInterface::ToJSVal(cx, value.m_Items[i].GetOriginalString())); 284 JS_SetElement(cx, obj, (uint32_t)i, val.address()); 282 285 } 283 286 284 287 break; … … 294 297 } 295 298 } 296 299 297 JSBool JSI_IGUIObject::setProperty(JSContext* cx, JS Object* obj, jsid id, JSBool UNUSED(strict), jsval*vp)300 JSBool JSI_IGUIObject::setProperty(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JSBool UNUSED(strict), JS::MutableHandle<jsval> vp) 298 301 { 299 302 IGUIObject* e = (IGUIObject*)JS_GetInstancePrivate(cx, obj, &JSI_IGUIObject::JSI_class, NULL); 300 303 if (!e) … … 311 314 if (propName == "name") 312 315 { 313 316 std::string value; 314 if (!ScriptInterface::FromJSVal(cx, *vp, value))317 if (!ScriptInterface::FromJSVal(cx, vp.get(), value)) 315 318 return JS_FALSE; 316 319 e->SetName(value); 317 320 return JS_TRUE; … … 320 323 // Use onWhatever to set event handlers 321 324 if (propName.substr(0, 2) == "on") 322 325 { 323 if ( !JSVAL_IS_OBJECT(*vp) || !JS_ObjectIsFunction(cx, JSVAL_TO_OBJECT(*vp)))326 if (JSVAL_IS_PRIMITIVE(vp.get()) || !JS_ObjectIsFunction(cx, JSVAL_TO_OBJECT(vp.get()))) 324 327 { 325 328 JS_ReportError(cx, "on- event-handlers must be functions"); 326 329 return JS_FALSE; 327 330 } 328 331 329 332 CStr eventName (CStr(propName.substr(2)).LowerCase()); 330 e->SetScriptHandler(eventName, JSVAL_TO_OBJECT( *vp));333 e->SetScriptHandler(eventName, JSVAL_TO_OBJECT(vp.get())); 331 334 332 335 return JS_TRUE; 333 336 } … … 346 349 case GUIST_CStr: 347 350 { 348 351 std::string value; 349 if (!ScriptInterface::FromJSVal(cx, *vp, value))352 if (!ScriptInterface::FromJSVal(cx, vp.get(), value)) 350 353 return JS_FALSE; 351 354 352 355 GUI<CStr>::SetSetting(e, propName, value); … … 356 359 case GUIST_CStrW: 357 360 { 358 361 std::wstring value; 359 if (!ScriptInterface::FromJSVal(cx, *vp, value))360 return JS_FALSE;362 if (!ScriptInterface::FromJSVal(cx, vp.get(), value)) 363 return false; 361 364 362 365 GUI<CStrW>::SetSetting(e, propName, value); 363 366 break; … … 366 369 case GUIST_CGUISpriteInstance: 367 370 { 368 371 std::string value; 369 if (!ScriptInterface::FromJSVal(cx, *vp, value))370 return JS_FALSE;372 if (!ScriptInterface::FromJSVal(cx, vp.get(), value)) 373 return false; 371 374 372 375 GUI<CGUISpriteInstance>::SetSetting(e, propName, CGUISpriteInstance(value)); 373 376 break; … … 376 379 case GUIST_CGUIString: 377 380 { 378 381 std::wstring value; 379 if (!ScriptInterface::FromJSVal(cx, *vp, value))382 if (!ScriptInterface::FromJSVal(cx, vp.get(), value)) 380 383 return JS_FALSE; 381 384 382 385 CGUIString str; … … 388 391 case GUIST_EAlign: 389 392 { 390 393 std::string value; 391 if (!ScriptInterface::FromJSVal(cx, *vp, value))394 if (!ScriptInterface::FromJSVal(cx, vp.get(), value)) 392 395 return JS_FALSE; 393 396 394 397 EAlign a; … … 407 410 case GUIST_EVAlign: 408 411 { 409 412 std::string value; 410 if (!ScriptInterface::FromJSVal(cx, *vp, value))413 if (!ScriptInterface::FromJSVal(cx, vp.get(), value)) 411 414 return JS_FALSE; 412 415 413 416 EVAlign a; … … 425 428 426 429 case GUIST_int: 427 430 { 428 int32 value;429 if (JS_ValueToInt32(cx, *vp, &value) == JS_TRUE)431 int32_t value; 432 if (JS_ValueToInt32(cx, vp.get(), &value) == true) 430 433 GUI<int>::SetSetting(e, propName, value); 431 434 else 432 435 { … … 438 441 439 442 case GUIST_float: 440 443 { 441 jsdouble value;442 if (JS_ValueToNumber(cx, *vp, &value) == JS_TRUE)444 double value; 445 if (JS_ValueToNumber(cx, vp.get(), &value) == true) 443 446 GUI<float>::SetSetting(e, propName, (float)value); 444 447 else 445 448 { … … 452 455 case GUIST_bool: 453 456 { 454 457 JSBool value; 455 if (JS_ValueToBoolean(cx, *vp, &value) == JS_TRUE)456 GUI<bool>::SetSetting(e, propName, value == JS_TRUE);458 if (JS_ValueToBoolean(cx, vp.get(), &value)) 459 GUI<bool>::SetSetting(e, propName, value); 457 460 else 458 461 { 459 462 JS_ReportError(cx, "Cannot convert value to bool"); … … 464 467 465 468 case GUIST_CClientArea: 466 469 { 467 if (JSVAL_IS_STRING( *vp))470 if (JSVAL_IS_STRING(vp.get())) 468 471 { 469 472 std::wstring value; 470 if (!ScriptInterface::FromJSVal(cx, *vp, value))473 if (!ScriptInterface::FromJSVal(cx, vp.get(), value)) 471 474 return JS_FALSE; 472 475 473 476 if (e->SetSetting(propName, value) != PSRETURN_OK) … … 476 479 return JS_FALSE; 477 480 } 478 481 } 479 else if ( JSVAL_IS_OBJECT(*vp) && JS_InstanceOf(cx, JSVAL_TO_OBJECT(*vp), &JSI_GUISize::JSI_class, NULL))482 else if (!JSVAL_IS_PRIMITIVE(vp.get()) && JS_InstanceOf(cx, JSVAL_TO_OBJECT(vp.get()), &JSI_GUISize::JSI_class, NULL)) 480 483 { 481 484 CClientArea area; 482 485 GUI<CClientArea>::GetSetting(e, propName, area); 483 486 484 JSObject* obj = JSVAL_TO_OBJECT( *vp);487 JSObject* obj = JSVAL_TO_OBJECT(vp.get()); 485 488 ScriptInterface* pScriptInterface = ScriptInterface::GetScriptInterfaceAndCBData(cx)->pScriptInterface; 486 489 #define P(x, y, z) pScriptInterface->GetProperty(OBJECT_TO_JSVAL(obj), #z, area.x.y) 487 490 P(pixel, left, left); … … 506 509 507 510 case GUIST_CColor: 508 511 { 509 if (JSVAL_IS_STRING( *vp))512 if (JSVAL_IS_STRING(vp.get())) 510 513 { 511 514 std::wstring value; 512 if (!ScriptInterface::FromJSVal(cx, *vp, value))515 if (!ScriptInterface::FromJSVal(cx, vp.get(), value)) 513 516 return JS_FALSE; 514 517 515 518 if (e->SetSetting(propName, value) != PSRETURN_OK) … … 518 521 return JS_FALSE; 519 522 } 520 523 } 521 else if ( JSVAL_IS_OBJECT(*vp) && JS_InstanceOf(cx, JSVAL_TO_OBJECT(*vp), &JSI_GUIColor::JSI_class, NULL))524 else if (!JSVAL_IS_PRIMITIVE(vp.get()) && JS_InstanceOf(cx, JSVAL_TO_OBJECT(vp.get()), &JSI_GUIColor::JSI_class, NULL)) 522 525 { 523 526 CColor colour; 524 JSObject* obj = JSVAL_TO_OBJECT(*vp); 525 jsval t; double s; 526 #define PROP(x) JS_GetProperty(cx, obj, #x, &t); \ 527 JSObject* obj = JSVAL_TO_OBJECT(vp.get()); 528 JS::RootedValue t(cx); 529 double s; 530 #define PROP(x) JS_GetProperty(cx, obj, #x, t.address()); \ 527 531 JS_ValueToNumber(cx, t, &s); \ 528 532 colour.x = (float)s 529 533 PROP(r); PROP(g); PROP(b); PROP(a); … … 541 545 542 546 case GUIST_CGUIList: 543 547 { 544 JSObject* obj = JSVAL_TO_OBJECT( *vp);545 jsuint length;546 if ( JSVAL_IS_OBJECT(*vp) && JS_GetArrayLength(cx, obj, &length) == JS_TRUE)548 JSObject* obj = JSVAL_TO_OBJECT(vp.get()); 549 uint length; 550 if (!JSVAL_IS_PRIMITIVE(vp.get()) && JS_GetArrayLength(cx, obj, &length) == true) 547 551 { 548 552 CGUIList list; 549 553 550 554 for (int i=0; i<(int)length; ++i) 551 555 { 552 jsval element;553 if (! JS_GetElement(cx, obj, i, &element))556 JS::RootedValue element(cx); 557 if (! JS_GetElement(cx, obj, i, element.address())) 554 558 { 555 559 JS_ReportError(cx, "Failed to get list element"); 556 560 return JS_FALSE; … … 562 566 563 567 CGUIString str; 564 568 str.SetValue(value); 565 569 566 570 list.m_Items.push_back(str); 567 571 } 568 572 … … 587 591 } 588 592 589 593 590 JSBool JSI_IGUIObject::construct(JSContext* cx, uint Nargc, jsval* vp)594 JSBool JSI_IGUIObject::construct(JSContext* cx, uint argc, jsval* vp) 591 595 { 592 596 if (argc == 0) 593 597 { … … 599 603 600 604 // Store the IGUIObject in the JS object's 'private' area 601 605 IGUIObject* guiObject = (IGUIObject*)JSVAL_TO_PRIVATE(JS_ARGV(cx, vp)[0]); 602 JS_SetPrivate( cx,obj, guiObject);606 JS_SetPrivate(obj, guiObject); 603 607 604 608 JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(obj)); 605 609 return JS_TRUE; … … 610 614 scriptInterface.DefineCustomObjectType(&JSI_class, construct, 1, JSI_props, JSI_methods, NULL, NULL); 611 615 } 612 616 613 JSBool JSI_IGUIObject::toString(JSContext* cx, uint Nargc, jsval* vp)617 JSBool JSI_IGUIObject::toString(JSContext* cx, uint argc, jsval* vp) 614 618 { 615 619 UNUSED2(argc); 616 620 … … 625 629 return JS_TRUE; 626 630 } 627 631 628 JSBool JSI_IGUIObject::focus(JSContext* cx, uint Nargc, jsval* vp)632 JSBool JSI_IGUIObject::focus(JSContext* cx, uint argc, jsval* vp) 629 633 { 630 634 UNUSED2(argc); 631 635 … … 639 643 return JS_TRUE; 640 644 } 641 645 642 JSBool JSI_IGUIObject::blur(JSContext* cx, uint Nargc, jsval* vp)646 JSBool JSI_IGUIObject::blur(JSContext* cx, uint argc, jsval* vp) 643 647 { 644 648 UNUSED2(argc); 645 649 … … 653 657 return JS_TRUE; 654 658 } 655 659 656 JSBool JSI_IGUIObject::getComputedSize(JSContext* cx, uint Nargc, jsval* vp)660 JSBool JSI_IGUIObject::getComputedSize(JSContext* cx, uint argc, jsval* vp) 657 661 { 658 662 UNUSED2(argc); 659 663 IGUIObject* e = (IGUIObject*)JS_GetInstancePrivate(cx, JS_THIS_OBJECT(cx, vp), &JSI_IGUIObject::JSI_class, NULL); -
source/gui/scripting/GuiScriptConversions.cpp
23 23 #include "lib/external_libraries/libsdl.h" 24 24 #include "ps/Hotkey.h" 25 25 26 #include "js/jsapi.h" 27 28 #define SET(obj, name, value) STMT(jsval v_ = ToJSVal(cx, (value)); JS_SetProperty(cx, (obj), (name), &v_)) 26 #define SET(obj, name, value) STMT(JS::RootedValue v_(cx, ToJSVal(cx, (value))); JS_SetProperty(cx, (obj), (name), v_.address())) 29 27 // ignore JS_SetProperty return value, because errors should be impossible 30 28 // and we can't do anything useful in the case of errors anyway 31 29 32 30 template<> jsval ScriptInterface::ToJSVal<SDL_Event_>(JSContext* cx, SDL_Event_ const& val) 33 31 { 32 JSAutoRequest rq(cx); 34 33 const char* typeName; 35 34 36 35 switch (val.ev.type) … … 78 77 JSObject* keysym = JS_NewObject(cx, NULL, NULL, NULL); 79 78 if (! keysym) 80 79 return JSVAL_VOID; 81 jsval keysymVal = OBJECT_TO_JSVAL(keysym);82 JS_SetProperty(cx, obj, "keysym", &keysymVal);80 JS::RootedValue keysymVal(cx, OBJECT_TO_JSVAL(keysym)); 81 JS_SetProperty(cx, obj, "keysym", keysymVal.address()); 83 82 84 83 // SET(keysym, "scancode", (int)val.ev.key.keysym.scancode); // (not in wsdl.h) 85 84 SET(keysym, "sym", (int)val.ev.key.keysym.sym); -
source/gui/scripting/JSInterface_IGUIObject.h
25 25 extern JSClass JSI_class; 26 26 extern JSPropertySpec JSI_props[]; 27 27 extern JSFunctionSpec JSI_methods[]; 28 JSBool getProperty(JSContext* cx, JS Object* obj, jsid id, jsval*vp);29 JSBool setProperty(JSContext* cx, JS Object* obj, jsid id, JSBool strict, jsval*vp);30 JSBool construct(JSContext* cx, uint Nargc, jsval* vp);31 JSBool toString(JSContext* cx, uint Nargc, jsval* vp);32 JSBool focus(JSContext* cx, uint Nargc, jsval* vp);33 JSBool blur(JSContext* cx, uint Nargc, jsval* vp);34 JSBool getComputedSize(JSContext* cx, uint Nargc, jsval* vp);28 JSBool getProperty(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JS::MutableHandle<jsval> vp); 29 JSBool setProperty(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JSBool UNUSED(strict), JS::MutableHandle<jsval> vp); 30 JSBool construct(JSContext* cx, uint argc, jsval* vp); 31 JSBool toString(JSContext* cx, uint argc, jsval* vp); 32 JSBool focus(JSContext* cx, uint argc, jsval* vp); 33 JSBool blur(JSContext* cx, uint argc, jsval* vp); 34 JSBool getComputedSize(JSContext* cx, uint argc, jsval* vp); 35 35 void init(ScriptInterface& scriptInterface); 36 36 } 37 37 -
source/gui/IGUIObject.h
142 142 friend class GUITooltip; 143 143 144 144 // Allow getProperty to access things like GetParent() 145 friend JSBool JSI_IGUIObject::getProperty(JSContext* cx, JS Object* obj, jsid id, jsval*vp);146 friend JSBool JSI_IGUIObject::setProperty(JSContext* cx, JS Object* obj, jsid id, JSBool strict, jsval*vp);147 friend JSBool JSI_IGUIObject::getComputedSize(JSContext* cx, uint Nargc, jsval* vp);145 friend JSBool JSI_IGUIObject::getProperty(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JS::MutableHandle<jsval> vp); 146 friend JSBool JSI_IGUIObject::setProperty(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JSBool UNUSED(strict), JS::MutableHandle<jsval> vp); 147 friend JSBool JSI_IGUIObject::getComputedSize(JSContext* cx, uint argc, jsval* vp); 148 148 149 149 public: 150 150 IGUIObject(); -
libraries/source/spidermonkey/build.sh
Kann nicht anzeigen: Dateityp ist als binär angegeben. svn:mime-type = application/octet-stream Kann nicht anzeigen: Dateityp ist als binär angegeben. svn:mime-type = application/octet-stream Kann nicht anzeigen: Dateityp ist als binär angegeben. svn:mime-type = application/octet-stream
17 17 echo "Building SpiderMonkey..." 18 18 echo 19 19 20 JOBS=${JOBS:="-j2"} 20 21 JOBS=${JOBS:="-j5"} 21 22 MAKE=${MAKE:="make"} 22 23 23 24 MAKE_OPTS="${JOBS}" 25 NSPR_INCLUDES="`pkg-config nspr --cflags`" 26 NSPR_LIBS="`pkg-config nspr --libs`" 24 27 25 CONF_OPTS="--disable-tests" 26 # (We don't use --enable-threadsafe because we don't use a single runtime in 27 # multiple threads, so it is unnecessary complexity and performance overhead) 28 CONF_OPTS="--disable-e4x --enable-threadsafe --enable-shared-js --disable-tests" # --enable-trace-logging" 28 29 29 30 # If Valgrind looks like it's installed, then set up SM to support it 30 31 # (else the JITs will interact poorly with it) … … 33 34 CONF_OPTS="${CONF_OPTS} --enable-valgrind" 34 35 fi 35 36 36 #CONF_OPTS="${CONF_OPTS} --enable-threadsafe --with-system-nspr"37 #CONF_OPTS="${CONF_OPTS} --enable-trace-jscalls"38 39 37 # We need to be able to override CHOST in case it is 32bit userland on 64bit kernel 40 38 CONF_OPTS="${CONF_OPTS} \ 41 39 ${CBUILD:+--build=${CBUILD}} \ … … 43 41 ${CTARGET:+--target=${CTARGET}}" 44 42 45 43 echo "SpiderMonkey build options: ${CONF_OPTS}" 44 echo ${CONF_OPTS} 46 45 47 # Extract the tarball 48 tar xzf js185-1.0.0.tar.gz 46 # Delete the existing directory to avoid conflicts and extract the tarball 47 rm -rf mozjs24 48 tar xjf mozjs-24.2.0.tar.bz2 49 49 50 # Apply patches 51 patch -p0 < openbsd-spidermonkey-650742.diff 52 patch -p0 < openbsd-spidermonkey-634609.diff 50 # Apply patches if needed 51 #patch -p0 < name_of_thepatch.diff 53 52 54 cd js-1.8.5/js/src 53 # rename the extracted directory to something shorter 54 mv mozjs-24.2.0 mozjs24 55 55 56 cd mozjs24/js/src 57 56 58 # We want separate debug/release versions of the library, so we have to change 57 59 # the LIBRARY_NAME for each build. 58 60 # (We use perl instead of sed so that it works with MozillaBuild on Windows, 59 61 # which has an ancient sed.) 60 perl -i.bak -pe 's/ ^(LIBRARY_NAME\s+= mozjs185)(-ps-debug|-ps-release)?/$1-ps-debug/' Makefile.in62 perl -i.bak -pe 's/(^LIBRARY_NAME\s+=).*/$1mozjs24-ps-debug/' Makefile.in 61 63 mkdir -p build-debug 62 64 cd build-debug 63 ../configure ${CONF_OPTS} -- enable-debug --disable-optimize65 ../configure ${CONF_OPTS} --with-nspr-libs="$NSPR_LIBS" --with-nspr-cflags="$NSPR_INCLUDES" --enable-debug --disable-optimize --enable-js-diagnostics --enable-gczeal # --enable-root-analysis 64 66 ${MAKE} ${MAKE_OPTS} 65 67 cd .. 66 68 67 perl -i.bak -pe 's/ ^(LIBRARY_NAME\s+= mozjs185)(-ps-debug|-ps-release)?/$1-ps-release/' Makefile.in69 perl -i.bak -pe 's/(^LIBRARY_NAME\s+=).*/$1mozjs24-ps-release/' Makefile.in 68 70 mkdir -p build-release 69 71 cd build-release 70 ../configure ${CONF_OPTS} # --enable-gczeal --enable-debug-symbols72 ../configure ${CONF_OPTS} --with-nspr-libs="$NSPR_LIBS" --with-nspr-cflags="$NSPR_INCLUDES" --enable-optimize # --enable-gczeal --enable-debug-symbols 71 73 ${MAKE} ${MAKE_OPTS} 72 74 cd .. 73 75 74 # Remove the library suffixes to avoid spurious SVN diffs75 perl -i.bak -pe 's/^(LIBRARY_NAME\s+= mozjs185)(-ps-debug|-ps-release)?/$1/' Makefile.in76 77 76 cd ../../.. 78 77 79 78 if [ "${OS}" = "Windows_NT" ] 80 79 then 81 INCLUDE_DIR=include-win32 80 INCLUDE_DIR_DEBUG=include-win32-debug 81 INCLUDE_DIR_RELEASE=include-win32-release 82 82 DLL_SRC_SUFFIX=-1.0.dll 83 83 DLL_DST_SUFFIX=-1.0.dll 84 84 LIB_PREFIX= … … 86 86 LIB_DST_SUFFIX=.lib 87 87 elif [ "`uname -s`" = "Darwin" ] 88 88 then 89 INCLUDE_DIR=include-unix 89 INCLUDE_DIR_DEBUG=include-unix-debug 90 INCLUDE_DIR_RELEASE=include-unix-release 90 91 DLL_SRC_SUFFIX=.dylib 91 92 DLL_DST_SUFFIX=.1.0.dylib 92 93 LIB_PREFIX=lib 93 94 LIB_SRC_SUFFIX=.dylib 94 95 LIB_DST_SUFFIX=.dylib 95 96 # Fix libtool's use of an absolute path 96 install_name_tool -id @executable_path/${LIB_PREFIX}mozjs 185-ps-debug${DLL_DST_SUFFIX} js-1.8.5/js/src/build-debug/dist/bin/${LIB_PREFIX}mozjs185-ps-debug${DLL_SRC_SUFFIX}97 install_name_tool -id @executable_path/${LIB_PREFIX}mozjs 185-ps-release${DLL_DST_SUFFIX} js-1.8.5/js/src/build-release/dist/bin/${LIB_PREFIX}mozjs185-ps-release${DLL_SRC_SUFFIX}97 install_name_tool -id @executable_path/${LIB_PREFIX}mozjs24-ps-debug${DLL_DST_SUFFIX} mozjs24/js/src/build-debug/dist/bin/${LIB_PREFIX}mozjs24-ps-debug${DLL_SRC_SUFFIX} 98 install_name_tool -id @executable_path/${LIB_PREFIX}mozjs24-ps-release${DLL_DST_SUFFIX} mozjs24/js/src/build-release/dist/bin/${LIB_PREFIX}mozjs24-ps-release${DLL_SRC_SUFFIX} 98 99 else 99 INCLUDE_DIR=include-unix 100 INCLUDE_DIR_DEBUG=include-unix-debug 101 INCLUDE_DIR_RELEASE=include-unix-release 100 102 DLL_SRC_SUFFIX=.so 101 DLL_DST_SUFFIX=.so .1.0103 DLL_DST_SUFFIX=.so 102 104 LIB_PREFIX=lib 103 105 LIB_SRC_SUFFIX=.so 104 106 LIB_DST_SUFFIX=.so … … 113 115 114 116 # Copy files into the necessary locations for building and running the game 115 117 116 # js-config.h is the same for both debug and release builds, so we only need to copy one 117 mkdir -p ${INCLUDE_DIR}/js 118 cp -L js-1.8.5/js/src/build-release/dist/include/* ${INCLUDE_DIR}/js/ 118 # js-config.h is different for debug and release builds, so we need different include directories for both 119 mkdir -p ${INCLUDE_DIR_DEBUG} 120 mkdir -p ${INCLUDE_DIR_RELEASE} 121 cp -R -L mozjs24/js/src/build-release/dist/include/* ${INCLUDE_DIR_RELEASE}/ 122 cp -R -L mozjs24/js/src/build-debug/dist/include/* ${INCLUDE_DIR_DEBUG}/ 119 123 120 124 mkdir -p lib/ 121 cp -L js-1.8.5/js/src/build-debug/dist/lib/${LIB_PREFIX}mozjs185-ps-debug${LIB_SRC_SUFFIX} lib/${LIB_PREFIX}mozjs185-ps-debug${LIB_DST_SUFFIX}122 cp -L js-1.8.5/js/src/build-release/dist/lib/${LIB_PREFIX}mozjs185-ps-release${LIB_SRC_SUFFIX} lib/${LIB_PREFIX}mozjs185-ps-release${LIB_DST_SUFFIX}123 cp -L js-1.8.5/js/src/build-debug/dist/bin/${LIB_PREFIX}mozjs185-ps-debug${DLL_SRC_SUFFIX} ../../../binaries/system/${LIB_PREFIX}mozjs185-ps-debug${DLL_DST_SUFFIX}124 cp -L js-1.8.5/js/src/build-release/dist/bin/${LIB_PREFIX}mozjs185-ps-release${DLL_SRC_SUFFIX} ../../../binaries/system/${LIB_PREFIX}mozjs185-ps-release${DLL_DST_SUFFIX}125 cp -L mozjs24/js/src/build-debug/dist/lib/${LIB_PREFIX}mozjs24-ps-debug${LIB_SRC_SUFFIX} lib/${LIB_PREFIX}mozjs24-ps-debug${LIB_DST_SUFFIX} 126 cp -L mozjs24/js/src/build-release/dist/lib/${LIB_PREFIX}mozjs24-ps-release${LIB_SRC_SUFFIX} lib/${LIB_PREFIX}mozjs24-ps-release${LIB_DST_SUFFIX} 127 cp -L mozjs24/js/src/build-debug/dist/bin/${LIB_PREFIX}mozjs24-ps-debug${DLL_SRC_SUFFIX} ../../../binaries/system/${LIB_PREFIX}mozjs24-ps-debug${DLL_DST_SUFFIX} 128 cp -L mozjs24/js/src/build-release/dist/bin/${LIB_PREFIX}mozjs24-ps-release${DLL_SRC_SUFFIX} ../../../binaries/system/${LIB_PREFIX}mozjs24-ps-release${DLL_DST_SUFFIX} 125 129 126 130 # Flag that it's already been built successfully so we can skip it next time 127 131 touch .already-built -
libraries/source/spidermonkey/README.txt
5 5 then run start-msvc8.bat and run ./build.sh here. 6 6 7 7 This version of SpiderMonkey comes from 8 http://ftp.mozilla.org/pub/mozilla.org/js/js185-1.0.0.tar.gz 9 (see also https://developer.mozilla.org/en/SpiderMonkey/1.8.5) 8 https://ftp.mozilla.org/pub/mozilla.org/js/mozjs-24.2.0.tar.bz2 10 9 11 The game must be compiled with precisely this version, and must not use a 12 standard system-provided version of the library, since SpiderMonkey does not 13 guarantee API stability and may have behavioural changes that cause subtle 14 bugs or network out-of-sync errors. 10 The game must be compiled with precisely this version since SpiderMonkey 11 does not guarantee API stability and may have behavioural changes that 12 cause subtle bugs or network out-of-sync errors. 13 A standard system-provided version of the library may only be used if it's 14 exactly the same version or if it's another minor release that does not 15 change the behaviour of the scripts executed by SpiderMonkey. -
libraries/source/spidermonkey/openbsd-spidermonkey-650742.diff
1 --- js-1.8.5/js/src/configure.in2 +++ js-1.8.5/js/src/configure.in3 @@ -3041,6 +3041,9 @@4 *-freebsd*|*-kfreebsd*)5 AC_DEFINE(AVMPLUS_UNIX)6 ;;7 +*-openbsd*)8 + AC_DEFINE(AVMPLUS_UNIX)9 + ;;10 *-gnu*)11 AC_DEFINE(AVMPLUS_UNIX)12 ;;13 --- js-1.8.5/js/src/configure14 +++ js-1.8.5/js/src/configure15 @@ -8093,6 +8093,12 @@16 EOF17 18 ;;19 +*-openbsd*)20 + cat >> confdefs.h <<\EOF21 +#define AVMPLUS_UNIX 122 +EOF23 +24 + ;;25 *-gnu*)26 cat >> confdefs.h <<\EOF27 #define AVMPLUS_UNIX 1 -
libraries/source/spidermonkey/openbsd-spidermonkey-634609.diff
1 --- js-1.8.5/js/src/jsnativestack.cpp2 +++ js-1.8.5/js/src/jsnativestack.cpp3 @@ -50,7 +50,7 @@4 #elif defined(XP_MACOSX) || defined(DARWIN) || defined(XP_UNIX)5 # include <pthread.h>6 7 -# if defined(__FreeBSD__)8 +# if defined(__FreeBSD__) || defined(__OpenBSD__)9 # include <pthread_np.h>10 # endif11 12 @@ -196,7 +196,9 @@13 # else14 pthread_attr_t sattr;15 pthread_attr_init(&sattr);16 -# if defined(PTHREAD_NP_H) || defined(_PTHREAD_NP_H_) || defined(NETBSD)17 +# if defined(__OpenBSD__)18 + stack_t ss;19 +# elif defined(PTHREAD_NP_H) || defined(_PTHREAD_NP_H_) || defined(NETBSD)20 /* e.g. on FreeBSD 4.8 or newer, neundorf@kde.org */21 pthread_attr_get_np(thread, &sattr);22 # else23 @@ -212,7 +214,13 @@24 # ifdef DEBUG25 int rc =26 # endif27 +# if defined(__OpenBSD__)28 + pthread_stackseg_np(pthread_self(), &ss);29 + stackBase = (void*)((size_t) ss.ss_sp - ss.ss_size);30 + stackSize = ss.ss_size;31 +# else32 pthread_attr_getstack(&sattr, &stackBase, &stackSize);33 +# endif34 JS_ASSERT(!rc);35 JS_ASSERT(stackBase);36 pthread_attr_destroy(&sattr);