Ticket #1886: patch_26_v0.7.diff
File patch_26_v0.7.diff, 152.2 KB (added by , 10 years ago) |
---|
-
libraries/source/spidermonkey/build.sh
14 14 exit 15 15 fi 16 16 17 echo "Building NSPR (required for Spidermonkey THREADSAFE build)" 18 echo 19 cd mozjs24/nsprpub 20 mkdir -p build-64 21 cd build-64 22 ../configure --disable-debug --enable-optimize --enable-64bit 23 make 24 cd ../../../ 25 26 17 27 echo "Building SpiderMonkey..." 18 28 echo 19 29 20 JOBS=${JOBS:="-j2"} 30 31 JOBS=${JOBS:="-j5"} 21 32 MAKE=${MAKE:="make"} 22 33 23 34 MAKE_OPTS="${JOBS}" 35 #--with-nspr-cflags='\ 36 NSPR_INCLUDES="-I/home/yves/Projekte/0ad_spidermonkey4/libraries/source/spidermonkey/mozjs24/nsprpub/build-64/dist/include/nspr" 37 NSPR_LIBS="/home/yves/Projekte/0ad_spidermonkey4/libraries/source/spidermonkey/mozjs24/nsprpub/build-64/dist/lib/libnspr4.a "\ 38 "/home/yves/Projekte/0ad_spidermonkey4/libraries/source/spidermonkey/mozjs24/nsprpub/build-64/dist/lib/libplc4.a "\ 39 "/home/yves/Projekte/0ad_spidermonkey4/libraries/source/spidermonkey/mozjs24/nsprpub/build-64/dist/lib/libplds4.a" 40 CONF_OPTS="--disable-e4x --enable-threadsafe --enable-shared-js" # --enable-trace-logging" # --disable-tests 24 41 25 CONF_OPTS="--disable-tests"26 42 # (We don't use --enable-threadsafe because we don't use a single runtime in 27 43 # multiple threads, so it is unnecessary complexity and performance overhead) 28 44 … … 43 59 ${CTARGET:+--target=${CTARGET}}" 44 60 45 61 echo "SpiderMonkey build options: ${CONF_OPTS}" 62 echo ${CONF_OPTS} 46 63 47 64 # Extract the tarball 48 tar xzf js185-1.0.0.tar.gz65 #tar xzf mozjs18.0.0.tar.gz 49 66 50 67 # Apply patches 51 patch -p0 < openbsd-spidermonkey-650742.diff52 patch -p0 < openbsd-spidermonkey-634609.diff68 #patch -p0 < openbsd-spidermonkey-650742.diff 69 #patch -p0 < openbsd-spidermonkey-634609.diff 53 70 54 cd js-1.8.5/js/src71 cd mozjs24/js/src 55 72 56 73 # We want separate debug/release versions of the library, so we have to change 57 74 # the LIBRARY_NAME for each build. 58 75 # (We use perl instead of sed so that it works with MozillaBuild on Windows, 59 76 # which has an ancient sed.) 60 perl -i.bak -pe 's/ ^(LIBRARY_NAME\s+= mozjs185)(-ps-debug|-ps-release)?/$1-ps-debug/' Makefile.in77 perl -i.bak -pe 's/(LIBRARY_NAME\s+=).*/$1 '\''mozjs24-ps-debug'\''/' moz.build 61 78 mkdir -p build-debug 62 79 cd build-debug 63 ../configure ${CONF_OPTS} --enable-debug --disable-optimize 80 ##../configure --disable-tests --disable-e4x --enable-threadsafe --with-nspr-cflags="-I./mozjs24/nsprpub/build-64/dist/include/nspr" --with-nspr-libs="./mozjs24/nsprpub/build-64/dist/lib/libnspr4.a ./mozjs24/nsprpub/build-64/dist/lib/libplc4.a ./mozjs24/nsprpub/build-64/dist/lib/libplds4.a" --enable-valgrind 81 ../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 82 ${MAKE} ${MAKE_OPTS} 65 83 cd .. 66 84 67 perl -i.bak -pe 's/ ^(LIBRARY_NAME\s+= mozjs185)(-ps-debug|-ps-release)?/$1-ps-release/' Makefile.in85 perl -i.bak -pe 's/(LIBRARY_NAME\s+=).*/$1 '\''mozjs24-ps-release'\''/' moz.build 68 86 mkdir -p build-release 69 87 cd build-release 70 ../configure ${CONF_OPTS} # --enable-gczeal --enable-debug-symbols88 ../configure ${CONF_OPTS} --with-nspr-libs="$NSPR_LIBS" --with-nspr-cflags="$NSPR_INCLUDES" --enable-optimize # --enable-gczeal --enable-debug-symbols 71 89 ${MAKE} ${MAKE_OPTS} 72 90 cd .. 73 91 74 92 # Remove the library suffixes to avoid spurious SVN diffs 75 perl -i.bak -pe 's/^(LIBRARY_NAME\s+= mozjs185)(-ps-debug|-ps-release)?/$1/' Makefile.in93 #perl -i.bak -pe 's/^(LIBRARY_NAME\s+= mozjs24)(-ps-debug|-ps-release)?/$1/' Makefile.in 76 94 77 95 cd ../../.. 78 96 … … 93 111 LIB_SRC_SUFFIX=.dylib 94 112 LIB_DST_SUFFIX=.dylib 95 113 # 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}114 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} 115 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 116 else 99 117 INCLUDE_DIR=include-unix 100 118 DLL_SRC_SUFFIX=.so 101 DLL_DST_SUFFIX=.so .1.0119 DLL_DST_SUFFIX=.so 102 120 LIB_PREFIX=lib 103 121 LIB_SRC_SUFFIX=.so 104 122 LIB_DST_SUFFIX=.so … … 114 132 # Copy files into the necessary locations for building and running the game 115 133 116 134 # js-config.h is the same for both debug and release builds, so we only need to copy one 117 mkdir -p ${INCLUDE_DIR} /js118 cp - L js-1.8.5/js/src/build-release/dist/include/* ${INCLUDE_DIR}/js/135 mkdir -p ${INCLUDE_DIR} 136 cp -R -L mozjs24/js/src/build-debug/dist/include/* ${INCLUDE_DIR}/ 119 137 120 138 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}139 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} 140 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} 141 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} 142 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 143 126 144 # Flag that it's already been built successfully so we can skip it next time 127 145 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 http://people.mozilla.org/~sstangl/mozjs17.0.0.rc1.tar.gz 10 9 11 10 The game must be compiled with precisely this version, and must not use a 12 11 standard system-provided version of the library, since SpiderMonkey does not -
build/premake/extern_libs4.lua
577 577 end 578 578 configuration "Debug" 579 579 includedirs { libraries_source_dir.."spidermonkey/"..include_dir } 580 defines { "DEBUG" } 580 581 configuration "Release" 581 582 includedirs { libraries_source_dir.."spidermonkey/"..include_dir } 582 583 configuration { } … … 591 592 end 592 593 else 593 594 configuration "Debug" 594 links { "mozjs 185-ps-debug" }595 links { "mozjs24-ps-debug" } 595 596 configuration "Release" 596 links { "mozjs 185-ps-release" }597 links { "mozjs24-ps-release" } 597 598 configuration { } 598 599 add_source_lib_paths("spidermonkey") 599 600 end -
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/Replay.cpp
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/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()));71 JS::RootedValue val(s->cx, ScriptInterface::ToJSVal( s->cx, CStrW(pathname.string()) )); 72 72 JS_SetElement(s->cx, s->filename_array, s->cur_idx++, &val); 73 73 return INFO::OK; 74 74 } … … 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());194 JS::RootedValue val(cx, ScriptInterface::ToJSVal(cx, CStr(line).FromUTF8())); 195 195 JS_SetElement(cx, line_array, cur_line++, &val); 196 196 } 197 197 -
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/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, uintNargc, jsval* vp); \30 JSBool toString(JSContext* cx, uintNargc, jsval* vp); \29 bool construct(JSContext* cx, uint argc, jsval* vp); \ 30 bool 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"72 #include "jsapi.h" 73 73 /* 74 74 * This file defines a set of functions that are available to GUI scripts, to allow 75 75 * interaction with the rest of the engine. … … 552 552 void ForceGC(ScriptInterface::CxPrivate* pCxPrivate) 553 553 { 554 554 double time = timer_Time(); 555 JS_GC(pCxPrivate->pScriptInterface->Get Context());555 JS_GC(pCxPrivate->pScriptInterface->GetJSRuntime()); 556 556 time = timer_Time() - time; 557 557 g_Console->InsertMessage(L"Garbage collection completed in: %f", time); 558 558 } -
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", JS I_IGUIObject::toString, 0, 0 },50 { "focus", JS I_IGUIObject::focus, 0, 0 },51 { "blur", JS I_IGUIObject::blur, 0, 0 },52 { "getComputedSize", JS I_IGUIObject::getComputedSize, 0, 0 },49 { "toString", JSOP_WRAPPER(JSI_IGUIObject::toString), 0, 0 }, 50 { "focus", JSOP_WRAPPER(JSI_IGUIObject::focus), 0, 0 }, 51 { "blur", JSOP_WRAPPER(JSI_IGUIObject::blur), 0, 0 }, 52 { "getComputedSize", JSOP_WRAPPER(JSI_IGUIObject::getComputedSize), 0, 0 }, 53 53 { 0 } 54 54 }; 55 55 56 JSBool JSI_IGUIObject::getProperty(JSContext* cx, JSObject* obj, jsid id, jsval*vp)56 bool 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) 60 return JS_FALSE;60 return false; 61 61 62 62 jsval idval; 63 63 if (!JS_IdToValue(cx, id, &idval)) 64 return JS_FALSE;64 return false; 65 65 66 66 std::string propName; 67 67 if (!ScriptInterface::FromJSVal(cx, idval, propName)) 68 return JS_FALSE;68 return false; 69 69 70 70 // Skip some things which are known to be functions rather than properties. 71 71 // ("constructor" *must* be here, else it'll try to GetSettingType before … … 80 80 propName == "blur" || 81 81 propName == "getComputedSize" 82 82 ) 83 return JS_TRUE;83 return true; 84 84 85 85 // Use onWhatever to access event handlers 86 86 if (propName.substr(0, 2) == "on") … … 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();94 return JS_TRUE;93 vp.set((*it).second.get()); 94 return true; 95 95 } 96 96 97 97 … … 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 return JS_TRUE;112 return 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()));118 return JS_TRUE;117 vp.set(STRING_TO_JSVAL(JS_NewStringCopyZ(cx, e->GetName().c_str()))); 118 return true; 119 119 } 120 120 // Handle all other properties 121 121 else … … 125 125 if (e->GetSettingType(propName, Type) != PSRETURN_OK) 126 126 { 127 127 JS_ReportError(cx, "Invalid GUIObject property '%s'", propName.c_str()); 128 return JS_FALSE;128 return false; 129 129 } 130 130 131 131 // (All the cases are in {...} to avoid scoping problems) … … 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) 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); 282 285 } 283 286 284 287 break; … … 287 290 default: 288 291 JS_ReportError(cx, "Setting '%s' uses an unimplemented type", propName.c_str()); 289 292 DEBUG_WARN_ERR(ERR::LOGIC); 290 return JS_FALSE;293 return false; 291 294 } 292 295 293 return JS_TRUE;296 return true; 294 297 } 295 298 } 296 299 297 JSBool JSI_IGUIObject::setProperty(JSContext* cx, JSObject* obj, jsid id, JSBool UNUSED(strict), jsval*vp)300 bool JSI_IGUIObject::setProperty(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, bool 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) 301 return JS_FALSE;304 return false; 302 305 303 306 jsval idval; 304 307 if (!JS_IdToValue(cx, id, &idval)) 305 return JS_FALSE;308 return false; 306 309 307 310 std::string propName; 308 311 if (!ScriptInterface::FromJSVal(cx, idval, propName)) 309 return JS_FALSE;312 return false; 310 313 311 314 if (propName == "name") 312 315 { 313 316 std::string value; 314 if (!ScriptInterface::FromJSVal(cx, *vp, value))315 return JS_FALSE;317 if (!ScriptInterface::FromJSVal(cx, vp.get(), value)) 318 return false; 316 319 e->SetName(value); 317 return JS_TRUE;320 return true; 318 321 } 319 322 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 return JS_FALSE;329 return 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 return JS_TRUE;335 return true; 333 336 } 334 337 335 338 // Retrieve the setting's type (and make sure it actually exists) … … 337 340 if (e->GetSettingType(propName, Type) != PSRETURN_OK) 338 341 { 339 342 JS_ReportError(cx, "Invalid setting '%s'", propName.c_str()); 340 return JS_TRUE;343 return true; 341 344 } 342 345 343 346 switch (Type) … … 346 349 case GUIST_CStr: 347 350 { 348 351 std::string value; 349 if (!ScriptInterface::FromJSVal(cx, *vp, value))350 return JS_FALSE;352 if (!ScriptInterface::FromJSVal(cx, vp.get(), value)) 353 return false; 351 354 352 355 GUI<CStr>::SetSetting(e, propName, value); 353 356 break; … … 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))380 return JS_FALSE;382 if (!ScriptInterface::FromJSVal(cx, vp.get(), value)) 383 return false; 381 384 382 385 CGUIString str; 383 386 str.SetValue(value); … … 388 391 case GUIST_EAlign: 389 392 { 390 393 std::string value; 391 if (!ScriptInterface::FromJSVal(cx, *vp, value))392 return JS_FALSE;394 if (!ScriptInterface::FromJSVal(cx, vp.get(), value)) 395 return false; 393 396 394 397 EAlign a; 395 398 if (value == "left") a = EAlign_Left; … … 398 401 else 399 402 { 400 403 JS_ReportError(cx, "Invalid alignment (should be 'left', 'right' or 'center')"); 401 return JS_FALSE;404 return false; 402 405 } 403 406 GUI<EAlign>::SetSetting(e, propName, a); 404 407 break; … … 407 410 case GUIST_EVAlign: 408 411 { 409 412 std::string value; 410 if (!ScriptInterface::FromJSVal(cx, *vp, value))411 return JS_FALSE;413 if (!ScriptInterface::FromJSVal(cx, vp.get(), value)) 414 return false; 412 415 413 416 EVAlign a; 414 417 if (value == "top") a = EVAlign_Top; … … 417 420 else 418 421 { 419 422 JS_ReportError(cx, "Invalid alignment (should be 'top', 'bottom' or 'center')"); 420 return JS_FALSE;423 return false; 421 424 } 422 425 GUI<EVAlign>::SetSetting(e, propName, a); 423 426 break; … … 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 { 433 436 JS_ReportError(cx, "Cannot convert value to int"); 434 return JS_FALSE;437 return false; 435 438 } 436 439 break; 437 440 } 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 { 446 449 JS_ReportError(cx, "Cannot convert value to float"); 447 return JS_FALSE;450 return false; 448 451 } 449 452 break; 450 453 } 451 454 452 455 case GUIST_bool: 453 456 { 454 JSBool value;455 if (JS_ValueToBoolean(cx, *vp, &value) == JS_TRUE)456 GUI<bool>::SetSetting(e, propName, value == JS_TRUE);457 bool value; 458 if (JS_ValueToBoolean(cx, vp.get(), &value) == true) 459 GUI<bool>::SetSetting(e, propName, value == true); 457 460 else 458 461 { 459 462 JS_ReportError(cx, "Cannot convert value to bool"); 460 return JS_FALSE;463 return false; 461 464 } 462 465 break; 463 466 } 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))471 return JS_FALSE;473 if (!ScriptInterface::FromJSVal(cx, vp.get(), value)) 474 return false; 472 475 473 476 if (e->SetSetting(propName, value) != PSRETURN_OK) 474 477 { 475 478 JS_ReportError(cx, "Invalid value for setting '%s'", propName.c_str()); 476 return JS_FALSE;479 return 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); … … 499 502 else 500 503 { 501 504 JS_ReportError(cx, "Size only accepts strings or GUISize objects"); 502 return JS_FALSE;505 return false; 503 506 } 504 507 break; 505 508 } 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))513 return JS_FALSE;515 if (!ScriptInterface::FromJSVal(cx, vp.get(), value)) 516 return false; 514 517 515 518 if (e->SetSetting(propName, value) != PSRETURN_OK) 516 519 { 517 520 JS_ReportError(cx, "Invalid value for setting '%s'", propName.c_str()); 518 return JS_FALSE;521 return 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; 527 JSObject* obj = JSVAL_TO_OBJECT(vp.get()); 528 JS::RootedValue t(cx); 529 double s; 526 530 #define PROP(x) JS_GetProperty(cx, obj, #x, &t); \ 527 531 JS_ValueToNumber(cx, t, &s); \ 528 532 colour.x = (float)s … … 534 538 else 535 539 { 536 540 JS_ReportError(cx, "Color only accepts strings or GUIColor objects"); 537 return JS_FALSE;541 return false; 538 542 } 539 543 break; 540 544 } 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;556 JS::RootedValue element(cx); 553 557 if (! JS_GetElement(cx, obj, i, &element)) 554 558 { 555 559 JS_ReportError(cx, "Failed to get list element"); 556 return JS_FALSE;560 return false; 557 561 } 558 562 559 563 std::wstring value; 560 564 if (!ScriptInterface::FromJSVal(cx, element, value)) 561 return JS_FALSE;565 return 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 … … 571 575 else 572 576 { 573 577 JS_ReportError(cx, "List only accepts a GUIList object"); 574 return JS_FALSE;578 return false; 575 579 } 576 580 break; 577 581 } … … 587 591 } 588 592 589 593 590 JSBool JSI_IGUIObject::construct(JSContext* cx, uintNargc, jsval* vp)594 bool JSI_IGUIObject::construct(JSContext* cx, uint argc, jsval* vp) 591 595 { 592 596 if (argc == 0) 593 597 { 594 598 JS_ReportError(cx, "GUIObject has no default constructor"); 595 return JS_FALSE;599 return false; 596 600 } 597 601 598 602 JSObject* obj = JS_NewObject(cx, &JSI_IGUIObject::JSI_class, NULL, NULL); 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 return JS_TRUE;609 return true; 606 610 } 607 611 608 612 void JSI_IGUIObject::init(ScriptInterface& scriptInterface) … … 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, uintNargc, jsval* vp)617 bool JSI_IGUIObject::toString(JSContext* cx, uint argc, jsval* vp) 614 618 { 615 619 UNUSED2(argc); 616 620 617 621 IGUIObject* e = (IGUIObject*)JS_GetInstancePrivate(cx, JS_THIS_OBJECT(cx, vp), &JSI_IGUIObject::JSI_class, NULL); 618 622 if (!e) 619 return JS_FALSE;623 return false; 620 624 621 625 char buffer[256]; 622 626 snprintf(buffer, 256, "[GUIObject: %s]", e->GetName().c_str()); 623 627 buffer[255] = 0; 624 628 JS_SET_RVAL(cx, vp, STRING_TO_JSVAL(JS_NewStringCopyZ(cx, buffer))); 625 return JS_TRUE;629 return true; 626 630 } 627 631 628 JSBool JSI_IGUIObject::focus(JSContext* cx, uintNargc, jsval* vp)632 bool JSI_IGUIObject::focus(JSContext* cx, uint argc, jsval* vp) 629 633 { 630 634 UNUSED2(argc); 631 635 632 636 IGUIObject* e = (IGUIObject*)JS_GetInstancePrivate(cx, JS_THIS_OBJECT(cx, vp), &JSI_IGUIObject::JSI_class, NULL); 633 637 if (!e) 634 return JS_FALSE;638 return false; 635 639 636 640 e->GetGUI()->SetFocusedObject(e); 637 641 638 642 JS_SET_RVAL(cx, vp, JSVAL_VOID); 639 return JS_TRUE;643 return true; 640 644 } 641 645 642 JSBool JSI_IGUIObject::blur(JSContext* cx, uintNargc, jsval* vp)646 bool JSI_IGUIObject::blur(JSContext* cx, uint argc, jsval* vp) 643 647 { 644 648 UNUSED2(argc); 645 649 646 650 IGUIObject* e = (IGUIObject*)JS_GetInstancePrivate(cx, JS_THIS_OBJECT(cx, vp), &JSI_IGUIObject::JSI_class, NULL); 647 651 if (!e) 648 return JS_FALSE;652 return false; 649 653 650 654 e->GetGUI()->SetFocusedObject(NULL); 651 655 652 656 JS_SET_RVAL(cx, vp, JSVAL_VOID); 653 return JS_TRUE;657 return true; 654 658 } 655 659 656 JSBool JSI_IGUIObject::getComputedSize(JSContext* cx, uintNargc, jsval* vp)660 bool 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); 660 664 if (!e) 661 return JS_FALSE;665 return false; 662 666 663 667 e->UpdateCachedSize(); 664 668 CRect size = e->m_CachedActualSize; … … 675 679 catch (PSERROR_Scripting_ConversionFailed&) 676 680 { 677 681 debug_warn(L"Error creating size object!"); 678 return JS_FALSE;682 return false; 679 683 } 680 684 681 685 JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(obj)); 682 return JS_TRUE;686 return true; 683 687 } -
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"26 #include "jsapi.h" 27 27 28 #define SET(obj, name, value) STMT( jsval v_ = ToJSVal(cx, (value)); JS_SetProperty(cx, (obj), (name), &v_))28 #define SET(obj, name, value) STMT(JS::RootedValue v_(cx, ToJSVal(cx, (value))); JS_SetProperty(cx, (obj), (name), v_)) 29 29 // ignore JS_SetProperty return value, because errors should be impossible 30 30 // and we can't do anything useful in the case of errors anyway 31 31 32 32 template<> jsval ScriptInterface::ToJSVal<SDL_Event_>(JSContext* cx, SDL_Event_ const& val) 33 33 { 34 JSAutoRequest rq(cx); 34 35 const char* typeName; 35 36 36 37 switch (val.ev.type) … … 78 79 JSObject* keysym = JS_NewObject(cx, NULL, NULL, NULL); 79 80 if (! keysym) 80 81 return JSVAL_VOID; 81 jsval keysymVal = OBJECT_TO_JSVAL(keysym);82 JS_SetProperty(cx, obj, "keysym", &keysymVal);82 JS::RootedValue keysymVal(cx, OBJECT_TO_JSVAL(keysym)); 83 JS_SetProperty(cx, obj, "keysym", keysymVal); 83 84 84 85 // SET(keysym, "scancode", (int)val.ev.key.keysym.scancode); // (not in wsdl.h) 85 86 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, JSObject* obj, jsid id, jsval*vp);29 JSBool setProperty(JSContext* cx, JSObject* obj, jsid id, JSBool strict, jsval*vp);30 JSBool construct(JSContext* cx, uintNargc, jsval* vp);31 JSBool toString(JSContext* cx, uintNargc, jsval* vp);32 JSBool focus(JSContext* cx, uintNargc, jsval* vp);33 JSBool blur(JSContext* cx, uintNargc, jsval* vp);34 JSBool getComputedSize(JSContext* cx, uintNargc, jsval* vp);28 bool getProperty(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JS::MutableHandle<jsval> vp); 29 bool setProperty(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, bool UNUSED(strict), JS::MutableHandle<jsval> vp); 30 bool construct(JSContext* cx, uint argc, jsval* vp); 31 bool toString(JSContext* cx, uint argc, jsval* vp); 32 bool focus(JSContext* cx, uint argc, jsval* vp); 33 bool blur(JSContext* cx, uint argc, jsval* vp); 34 bool getComputedSize(JSContext* cx, uint argc, jsval* vp); 35 35 void init(ScriptInterface& scriptInterface); 36 36 } 37 37 -
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", JS I_GUISize::toString, 0, 0 },48 { "toString", JSOP_WRAPPER(JSI_GUISize::toString), 0, 0 }, 49 49 { 0 } 50 50 }; 51 51 52 JSBool JSI_GUISize::construct(JSContext* cx, uintNargc, jsval* vp)52 bool 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); 68 JS_SetProperty(cx, obj, "top", v1); 69 JS_SetProperty(cx, obj, "right", v2); 70 JS_SetProperty(cx, obj, "bottom", v3); 71 JS_SetProperty(cx, obj, "rleft", v4); 72 JS_SetProperty(cx, obj, "rtop", v5); 73 JS_SetProperty(cx, obj, "rright", v6); 74 JS_SetProperty(cx, obj, "rbottom", v7); 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); 84 JS_SetProperty(cx, obj, "top", v1); 85 JS_SetProperty(cx, obj, "right", v2); 86 JS_SetProperty(cx, obj, "bottom", v3); 87 JS_SetProperty(cx, obj, "rleft", zero); 88 JS_SetProperty(cx, obj, "rtop", zero); 89 JS_SetProperty(cx, obj, "rright", zero); 90 JS_SetProperty(cx, obj, "rbottom", zero); 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); 96 JS_SetProperty(cx, obj, "top", zero); 97 JS_SetProperty(cx, obj, "right", zero); 98 JS_SetProperty(cx, obj, "bottom", zero); 99 JS_SetProperty(cx, obj, "rleft", zero); 100 JS_SetProperty(cx, obj, "rtop", zero); 101 JS_SetProperty(cx, obj, "rright", zero); 102 JS_SetProperty(cx, obj, "rbottom", zero); 90 103 } 91 104 92 105 JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(obj)); 93 return JS_TRUE;106 return true; 94 107 } 95 108 96 109 // Produces "10", "-10", "50%", "50%-10", "50%+10", etc … … 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, uintNargc, jsval* vp)118 bool JSI_GUISize::toString(JSContext* cx, uint argc, jsval* vp) 106 119 { 107 120 UNUSED2(argc); 108 121 … … 128 141 catch (PSERROR_Scripting_ConversionFailed&) 129 142 { 130 143 JS_SET_RVAL(cx, vp, STRING_TO_JSVAL(JS_NewStringCopyZ(cx, "<Error converting value to numbers>"))); 131 return JS_TRUE;144 return true; 132 145 } 133 146 134 147 JS_SET_RVAL(cx, vp, STRING_TO_JSVAL(JS_NewStringCopyZ(cx, buffer.c_str()))); 135 return JS_TRUE;148 return true; 136 149 } 137 150 138 151 … … 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 … … 163 176 { 0 } 164 177 }; 165 178 166 JSBool JSI_GUIColor::construct(JSContext* cx, uintNargc, jsval* vp)179 bool 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 170 183 if (argc == 4) 171 184 { 172 JS_SetProperty(cx, obj, "r", &JS_ARGV(cx, vp)[0]);173 JS_SetProperty(cx, obj, "g", &JS_ARGV(cx, vp)[1]);174 JS_SetProperty(cx, obj, "b", &JS_ARGV(cx, vp)[2]);175 JS_SetProperty(cx, obj, "a", &JS_ARGV(cx, vp)[3]);185 JS_SetProperty(cx, obj, "r", JS::RootedValue(cx, JS_ARGV(cx, vp)[0])); 186 JS_SetProperty(cx, obj, "g", JS::RootedValue(cx, JS_ARGV(cx, vp)[1])); 187 JS_SetProperty(cx, obj, "b", JS::RootedValue(cx, JS_ARGV(cx, vp)[2])); 188 JS_SetProperty(cx, obj, "a", JS::RootedValue(cx, JS_ARGV(cx, vp)[3])); 176 189 } 177 190 else 178 191 { 179 192 // Nice magenta: 180 jsval c; 181 if (!JS_NewNumberValue(cx, 1.0, &c)) 182 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)) 187 return JS_FALSE; 188 JS_SetProperty(cx, obj, "g", &c); 193 JS::RootedValue c(cx, JS_NumberValue(1.0)); 194 if (JSVAL_IS_NULL(c)) 195 return false; 196 JS_SetProperty(cx, obj, "r", c); 197 JS_SetProperty(cx, obj, "b", c); 198 JS_SetProperty(cx, obj, "a", c); 199 c = JS_NumberValue(0.0); 200 if (JSVAL_IS_NULL(c)) 201 return false; 202 JS_SetProperty(cx, obj, "g", c); 189 203 } 190 204 191 205 JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(obj)); 192 return JS_TRUE;206 return true; 193 207 } 194 208 195 JSBool JSI_GUIColor::toString(JSContext* cx, uintNargc, jsval* vp)209 bool JSI_GUIColor::toString(JSContext* cx, uint argc, jsval* vp) 196 210 { 197 211 UNUSED2(argc); 198 212 … … 210 224 (int)(255.0 * b), 211 225 (int)(255.0 * a)); 212 226 JS_SET_RVAL(cx, vp, STRING_TO_JSVAL(JS_NewStringCopyZ(cx, buffer))); 213 return JS_TRUE;227 return true; 214 228 } 215 229 216 230 /**** GUIMouse ****/ … … 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 … … 239 253 { 0 } 240 254 }; 241 255 242 JSBool JSI_GUIMouse::construct(JSContext* cx, uintNargc, jsval* vp)256 bool 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); 266 JS_SetProperty(cx, obj, "y", v1); 267 JS_SetProperty(cx, obj, "buttons", v2); 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); 273 JS_SetProperty(cx, obj, "y", zero); 274 JS_SetProperty(cx, obj, "buttons", zero); 258 275 } 259 276 260 277 JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(obj)); 261 return JS_TRUE;278 return true; 262 279 } 263 280 264 JSBool JSI_GUIMouse::toString(JSContext* cx, uintNargc, jsval* vp)281 bool 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); … … 274 291 char buffer[256]; 275 292 snprintf(buffer, 256, "%d %d %d", x, y, buttons); 276 293 JS_SET_RVAL(cx, vp, STRING_TO_JSVAL(JS_NewStringCopyZ(cx, buffer))); 277 return JS_TRUE;294 return true; 278 295 } 279 296 280 297 -
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/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, JSObject* obj, jsid id, jsval*vp);146 friend JSBool JSI_IGUIObject::setProperty(JSContext* cx, JSObject* obj, jsid id, JSBool strict, jsval*vp);147 friend JSBool JSI_IGUIObject::getComputedSize(JSContext* cx, uintNargc, jsval* vp);145 friend bool JSI_IGUIObject::getProperty(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JS::MutableHandle<jsval> vp); 146 friend bool JSI_IGUIObject::setProperty(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, bool UNUSED(strict), JS::MutableHandle<jsval> vp); 147 friend bool JSI_IGUIObject::getComputedSize(JSContext* cx, uint argc, jsval* vp); 148 148 149 149 public: 150 150 IGUIObject(); -
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/system/InterfaceScripted.h
19 19 #define INCLUDED_INTERFACE_SCRIPTED 20 20 21 21 #include "scriptinterface/ScriptInterface.h" 22 #include "js /jsapi.h"22 #include "jsapi.h" 23 23 24 24 #define BEGIN_INTERFACE_WRAPPER(iname) \ 25 25 JSClass class_ICmp##iname = { \ 26 26 "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 \ 27 JS_PropertyStub, JS_DeletePropertyStub, JS_PropertyStub, JS_StrictPropertyStub, \ 28 JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub \ 30 29 }; \ 31 30 static JSFunctionSpec methods_ICmp##iname[] = { 32 31 … … 35 34 }; \ 36 35 void ICmp##iname::InterfaceInit(ScriptInterface& scriptInterface) { \ 37 36 JSContext* cx = scriptInterface.GetContext(); \ 38 JSObject* global = JS_GetGlobalObject(cx); \ 37 JSAutoRequest rq(cx); \ 38 JSObject* global = JS::CurrentGlobalOrNull(cx); \ 39 39 JS_InitClass(cx, global, NULL, &class_ICmp##iname, NULL, 0, NULL, methods_ICmp##iname, NULL, NULL); \ 40 40 } \ 41 41 JSClass* ICmp##iname::GetJSClass() const { return &class_ICmp##iname; } \ … … 45 45 46 46 #define DEFINE_INTERFACE_METHOD_0(scriptname, rettype, classname, methodname) \ 47 47 { scriptname, \ 48 ScriptInterface::callMethod<rettype, &class_##classname, classname, &classname::methodname>, \48 { ScriptInterface::callMethod<rettype, &class_##classname, classname, &classname::methodname>, NULL }, \ 49 49 0, \ 50 50 JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT }, 51 51 52 52 #define DEFINE_INTERFACE_METHOD_1(scriptname, rettype, classname, methodname, arg1) \ 53 53 { scriptname, \ 54 ScriptInterface::callMethod<rettype, arg1, &class_##classname, classname, &classname::methodname>, \54 { ScriptInterface::callMethod<rettype, arg1, &class_##classname, classname, &classname::methodname>, NULL}, \ 55 55 1, \ 56 56 JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT }, 57 57 58 58 #define DEFINE_INTERFACE_METHOD_2(scriptname, rettype, classname, methodname, arg1, arg2) \ 59 59 { scriptname, \ 60 ScriptInterface::callMethod<rettype, arg1, arg2, &class_##classname, classname, &classname::methodname>, \60 { ScriptInterface::callMethod<rettype, arg1, arg2, &class_##classname, classname, &classname::methodname>, NULL }, \ 61 61 2, \ 62 62 JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT }, 63 63 64 64 #define DEFINE_INTERFACE_METHOD_3(scriptname, rettype, classname, methodname, arg1, arg2, arg3) \ 65 65 { scriptname, \ 66 ScriptInterface::callMethod<rettype, arg1, arg2, arg3, &class_##classname, classname, &classname::methodname>, \66 { ScriptInterface::callMethod<rettype, arg1, arg2, arg3, &class_##classname, classname, &classname::methodname>, NULL }, \ 67 67 3, \ 68 68 JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT }, 69 69 70 70 #define DEFINE_INTERFACE_METHOD_4(scriptname, rettype, classname, methodname, arg1, arg2, arg3, arg4) \ 71 71 { scriptname, \ 72 ScriptInterface::callMethod<rettype, arg1, arg2, arg3, arg4, &class_##classname, classname, &classname::methodname>, \72 { ScriptInterface::callMethod<rettype, arg1, arg2, arg3, arg4, &class_##classname, classname, &classname::methodname>, NULL }, \ 73 73 4, \ 74 74 JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT }, 75 75 76 76 #define DEFINE_INTERFACE_METHOD_5(scriptname, rettype, classname, methodname, arg1, arg2, arg3, arg4, arg5) \ 77 77 { scriptname, \ 78 ScriptInterface::callMethod<rettype, arg1, arg2, arg3, arg4, arg5, &class_##classname, classname, &classname::methodname>, \78 { ScriptInterface::callMethod<rettype, arg1, arg2, arg3, arg4, arg5, &class_##classname, classname, &classname::methodname>, NULL }, \ 79 79 5, \ 80 80 JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT }, 81 81 82 82 #define DEFINE_INTERFACE_METHOD_6(scriptname, rettype, classname, methodname, arg1, arg2, arg3, arg4, arg5, arg6) \ 83 83 { scriptname, \ 84 ScriptInterface::callMethod<rettype, arg1, arg2, arg3, arg4, arg5, arg6, &class_##classname, classname, &classname::methodname>, \84 { ScriptInterface::callMethod<rettype, arg1, arg2, arg3, arg4, arg5, arg6, &class_##classname, classname, &classname::methodname>, NULL }, \ 85 85 6, \ 86 86 JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT }, 87 87 88 88 #define DEFINE_INTERFACE_METHOD_7(scriptname, rettype, classname, methodname, arg1, arg2, arg3, arg4, arg5, arg6, arg7) \ 89 89 { scriptname, \ 90 ScriptInterface::callMethod<rettype, arg1, arg2, arg3, arg4, arg5, arg6, arg7, &class_##classname, classname, &classname::methodname>, \90 { ScriptInterface::callMethod<rettype, arg1, arg2, arg3, arg4, arg5, arg6, arg7, &class_##classname, classname, &classname::methodname>, NULL }, \ 91 91 7, \ 92 92 JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT }, 93 93 -
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"28 #include "jsapi.h" 29 29 30 30 #include <sstream> 31 31 … … 328 328 329 329 jsval CParamNode::ConstructJSVal(JSContext* cx) const 330 330 { 331 JSAutoRequest rq(cx); 331 332 if (m_Childs.empty()) 332 333 { 333 334 // Empty node - map to undefined … … 351 352 352 353 for (std::map<std::string, CParamNode>::const_iterator it = m_Childs.begin(); it != m_Childs.end(); ++it) 353 354 { 354 jsval childVal = it->second.ConstructJSVal(cx);355 if (!JS_SetProperty(cx, obj, it->first.c_str(), &childVal))355 JS::RootedValue childVal(cx, it->second.ConstructJSVal(cx)); 356 if (!JS_SetProperty(cx, obj, it->first.c_str(), childVal)) 356 357 return JSVAL_VOID; // TODO: report error 357 358 } 358 359 … … 363 364 JSString* str = JS_InternUCStringN(cx, reinterpret_cast<const jschar*>(text.data()), text.length()); 364 365 if (!str) 365 366 return JSVAL_VOID; // TODO: report error 366 jsval childVal = STRING_TO_JSVAL(str);367 if (!JS_SetProperty(cx, obj, "_string", &childVal))367 JS::RootedValue childVal(cx, STRING_TO_JSVAL(str)); 368 if (!JS_SetProperty(cx, obj, "_string", childVal)) 368 369 return JSVAL_VOID; // TODO: report error 369 370 } 370 371 -
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/components/ICmpCommandQueue.cpp
16 16 */ 17 17 18 18 #include "precompiled.h" 19 #include "jsapi.h" 19 20 20 21 #include "ICmpCommandQueue.h" 21 22 -
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 { … … 213 215 // to prevent frequent AI out-of-memory crashes. The argument should be 214 216 // removed as soon whenever the new pathfinder is committed 215 217 // 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)), 218 m_ScriptInterface(new ScriptInterface("Engine", "AI", g_ScriptRuntime)), 218 219 m_TurnNum(0), 219 220 m_CommandsComputed(true), 220 221 m_HasLoadedEntityTemplates(false), … … 305 306 static void ForceGC(ScriptInterface::CxPrivate* pCxPrivate) 306 307 { 307 308 PROFILE3("AI compute GC"); 308 JS_GC(pCxPrivate->pScriptInterface->Get Context());309 JS_GC(pCxPrivate->pScriptInterface->GetJSRuntime()); 309 310 } 310 311 311 312 /** … … 408 409 m_ScriptInterface->Eval("({})", fakeTech); 409 410 m_ScriptInterface->SetProperty(settings.get(), "techTemplates", fakeTech, false); 410 411 } 411 m_SharedAIObj = CScriptValRooted(m_ScriptInterface->GetContext(),m_ScriptInterface->CallConstructor(ctor.get(), settings.get())); 412 413 JS::AutoValueVector argv(m_ScriptInterface->GetContext()); 414 argv.append(settings.get()); 415 m_SharedAIObj = CScriptValRooted(m_ScriptInterface->GetContext(),m_ScriptInterface->CallConstructor(ctor.get(), argv.length(), argv.handleAt(0))); 412 416 413 417 414 418 if (m_SharedAIObj.undefined()) … … 754 758 m_Players[i]->Run(state, m_Players[i]->m_Player); 755 759 } 756 760 761 /* 757 762 // Run GC if we are about to overflow 758 763 if (JS_GetGCParameter(m_ScriptInterface->GetJSRuntime(), JSGC_BYTES) > 33000000) 759 764 { 760 765 PROFILE3("AI compute GC"); 761 766 762 JS_GC(m_ScriptInterface->Get Context());767 JS_GC(m_ScriptInterface->GetJSRuntime()); 763 768 } 764 769 */ 765 770 // Run the GC every so often. 766 771 // (This isn't particularly necessary, but it makes profiling clearer 767 772 // 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); 45 JS_SetProperty(cx, obj, "radius", pradius); 46 JS_SetProperty(cx, obj, "height", pheight); 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); 55 JS_SetProperty(cx, obj, "width", pwidth); 56 JS_SetProperty(cx, obj, "depth", pdepth); 57 JS_SetProperty(cx, obj, "height", pheight); 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"24 #include "jsapi.h" 25 25 26 26 #define TOJSVAL_SETUP() \ 27 JSObject* obj = JS_NewObject(scriptInterface.GetContext(), NULL, NULL, NULL); \ 28 if (! obj) \ 29 return JSVAL_VOID; 27 JSObject* obj; \ 28 {\ 29 JSAutoRequest rq(scriptInterface.GetContext()); \ 30 obj = JS_NewObject(scriptInterface.GetContext(), NULL, NULL, NULL); \ 31 if (!obj) \ 32 return JSVAL_VOID; \ 33 } 30 34 31 35 #define SET_MSG_PROPERTY(name) \ 32 36 do { \ 33 jsval prop = ScriptInterface::ToJSVal(scriptInterface.GetContext(), this->name); \ 34 if (! JS_SetProperty(scriptInterface.GetContext(), obj, #name, &prop)) \ 37 JSAutoRequest rq(scriptInterface.GetContext()); \ 38 JSContext* cx = scriptInterface.GetContext(); \ 39 JS::RootedValue prop(cx, ScriptInterface::ToJSVal(cx, this->name)); \ 40 if (! JS_SetProperty(cx, obj, #name, prop)) \ 35 41 return JSVAL_VOID; \ 36 42 } while (0); 37 43 38 44 #define FROMJSVAL_SETUP() \ 39 if ( ! JSVAL_IS_OBJECT(val)) \45 if ( JSVAL_IS_PRIMITIVE(val)) \ 40 46 return NULL; \ 41 47 JSObject* obj = JSVAL_TO_OBJECT(val); \ 42 jsval prop;48 JS::RootedValue prop(scriptInterface.GetContext()); 43 49 44 50 #define GET_MSG_PROPERTY(type, name) \ 51 type name; \ 52 { \ 53 JSAutoRequest rq(scriptInterface.GetContext()); \ 45 54 if (! JS_GetProperty(scriptInterface.GetContext(), obj, #name, &prop)) \ 46 55 return NULL; \ 47 type name; \48 56 if (! ScriptInterface::FromJSVal(scriptInterface.GetContext(), prop, name)) \ 49 return NULL; 57 return NULL; \ 58 } 50 59 51 60 jsval CMessage::ToJSValCached(ScriptInterface& scriptInterface) const 52 61 { -
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; 96 JS::RootedValue r(cx); 97 JS::RootedValue g(cx); 98 JS::RootedValue b(cx); 99 JS::RootedValue a(cx); 94 100 if (!JS_GetProperty(cx, obj, "r", &r) || !FromJSVal(cx, r, out.r)) 95 101 FAIL("Failed to get property CColor.r"); 96 102 if (!JS_GetProperty(cx, obj, "g", &g) || !FromJSVal(cx, g, out.g)) … … 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); 126 JS_SetProperty(cx, obj, "g", g); 127 JS_SetProperty(cx, obj, "b", b); 128 JS_SetProperty(cx, obj, "a", a); 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); … … 136 144 137 145 template<> jsval ScriptInterface::ToJSVal<fixed>(JSContext* 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 161 if (!JS_GetProperty(cx, obj, "x", &p)) return false; // TODO: report type errors 153 162 if (!FromJSVal(cx, p, out.X)) return false; … … 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); 185 JS_SetProperty(cx, obj, "y", y); 186 JS_SetProperty(cx, obj, "z", z); 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 200 if (!JS_GetProperty(cx, obj, "x", &p)) return false; // TODO: report type errors 190 201 if (!FromJSVal(cx, p, out.X)) return false; … … 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); 220 JS_SetProperty(cx, obj, "y", y); 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); 240 JS_SetProperty(cx, obj, "height", h); 241 JS_SetProperty(cx, obj, "data", data); 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); 260 JS_SetProperty(cx, obj, "height", h); 261 JS_SetProperty(cx, obj, "data", data); 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/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"28 #include "jsapi.h" 29 29 30 30 #include "lib/byte_order.h" 31 31 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 32 CStdDeserializer::CStdDeserializer(ScriptInterface& scriptInterface, std::istream& stream) : 60 33 m_ScriptInterface(scriptInterface), m_Stream(stream) 61 34 { … … 141 114 std::map<u32, JSObject*>::iterator it = m_ScriptBackrefs.begin(); 142 115 for (; it != m_ScriptBackrefs.end(); ++it) 143 116 { 144 if (!JS_RemoveObjectRoot(m_ScriptInterface.GetContext(), &it->second)) 145 throw PSERROR_Deserialize_ScriptError("JS_RemoveRoot failed"); 117 JS_RemoveObjectRoot(m_ScriptInterface.GetContext(), &it->second); 146 118 } 147 119 m_ScriptBackrefs.clear(); 148 120 } … … 192 164 if (!proto) 193 165 throw PSERROR_Deserialize_ScriptError("Failed to find serializable prototype for object"); 194 166 195 JSObject* parent = JS_GetParent( cx,proto);167 JSObject* parent = JS_GetParent(proto); 196 168 if (!proto || !parent) 197 169 throw PSERROR_Deserialize_ScriptError(); 198 170 … … 203 175 204 176 // Does it have custom Deserialize function? 205 177 // if so, we let it handle the deserialized data, rather than adding properties directly 206 JSBool hasCustomDeserialize, hasCustomSerialize;178 bool hasCustomDeserialize, hasCustomSerialize; 207 179 if (!JS_HasProperty(cx, obj, "Serialize", &hasCustomSerialize) || !JS_HasProperty(cx, obj, "Deserialize", &hasCustomDeserialize)) 208 180 throw PSERROR_Serialize_ScriptError("JS_HasProperty failed"); 209 181 210 182 if (hasCustomDeserialize) 211 183 { 212 jsval serialize;184 JS::RootedValue serialize(cx); 213 185 if (!JS_LookupProperty(cx, obj, "Serialize", &serialize)) 214 186 throw PSERROR_Serialize_ScriptError("JS_LookupProperty failed"); 215 187 bool hasNullSerialize = hasCustomSerialize && JSVAL_IS_NULL(serialize); … … 241 213 utf16string propname; 242 214 ReadStringUTF16("prop name", propname); 243 215 244 jsval propval = ReadScriptVal("prop value", NULL);216 JS::RootedValue propval(cx, ReadScriptVal("prop value", NULL)); 245 217 CScriptValRooted propvalRoot(cx, propval); 246 218 247 if (!JS_SetUCProperty(cx, obj, (const jschar*)propname.data(), propname.length(), &propval))219 if (!JS_SetUCProperty(cx, obj, (const jschar*)propname.data(), propname.length(), propval)) 248 220 throw PSERROR_Deserialize_ScriptError(); 249 221 } 250 222 … … 266 238 { 267 239 double value; 268 240 NumberDouble_Unbounded("value", value); 269 jsval rval ;270 if ( !JS_NewNumberValue(cx, value, &rval))241 jsval rval = JS_NumberValue(value); 242 if (JSVAL_IS_NULL(rval)) 271 243 throw PSERROR_Deserialize_ScriptError("JS_NewNumberValue failed"); 272 244 return rval; 273 245 } … … 275 247 { 276 248 uint8_t value; 277 249 NumberU8("value", value, 0, 1); 278 return BOOLEAN_TO_JSVAL(value ? JS_TRUE : JS_FALSE);250 return BOOLEAN_TO_JSVAL(value ? true : false); 279 251 } 280 252 case SCRIPT_TYPE_BACKREF: 281 253 { … … 290 262 { 291 263 double value; 292 264 NumberDouble_Unbounded("value", value); 293 jsval val; 294 if (!JS_NewNumberValue(cx, value, &val)) 295 throw PSERROR_Deserialize_ScriptError(); 265 JS::RootedValue val(cx, JS_NumberValue(value)); 296 266 CScriptValRooted objRoot(cx, val); 297 267 298 268 JSObject* ctorobj; 299 if (!JS_GetClassObject(cx, JS _GetGlobalObject(cx), JSProto_Number, &ctorobj))269 if (!JS_GetClassObject(cx, JS::CurrentGlobalOrNull(cx), JSProto_Number, &ctorobj)) 300 270 throw PSERROR_Deserialize_ScriptError("JS_GetClassObject failed"); 301 271 302 JSObject* obj = JS_New(cx, ctorobj, 1, &val);272 JSObject* obj = JS_New(cx, ctorobj, 1, val.address()); 303 273 if (!obj) 304 274 throw PSERROR_Deserialize_ScriptError("JS_New failed"); 305 275 AddScriptBackref(obj); … … 311 281 ScriptString("value", str); 312 282 if (!str) 313 283 throw PSERROR_Deserialize_ScriptError(); 314 jsval val = STRING_TO_JSVAL(str);284 JS::RootedValue val(cx, STRING_TO_JSVAL(str)); 315 285 CScriptValRooted valRoot(cx, val); 316 286 317 287 JSObject* ctorobj; 318 if (!JS_GetClassObject(cx, JS _GetGlobalObject(cx), JSProto_String, &ctorobj))288 if (!JS_GetClassObject(cx, JS::CurrentGlobalOrNull(cx), JSProto_String, &ctorobj)) 319 289 throw PSERROR_Deserialize_ScriptError("JS_GetClassObject failed"); 320 290 321 JSObject* obj = JS_New(cx, ctorobj, 1, &val);291 JSObject* obj = JS_New(cx, ctorobj, 1, val.address()); 322 292 if (!obj) 323 293 throw PSERROR_Deserialize_ScriptError("JS_New failed"); 324 294 AddScriptBackref(obj); … … 328 298 { 329 299 bool value; 330 300 Bool("value", value); 331 jsval val = BOOLEAN_TO_JSVAL(value ? JS_TRUE : JS_FALSE); 332 CScriptValRooted objRoot(cx, val); 301 JS::RootedValue val(cx, BOOLEAN_TO_JSVAL(value)); 333 302 334 303 JSObject* ctorobj; 335 if (!JS_GetClassObject(cx, JS _GetGlobalObject(cx), JSProto_Boolean, &ctorobj))304 if (!JS_GetClassObject(cx, JS::CurrentGlobalOrNull(cx), JSProto_Boolean, &ctorobj)) 336 305 throw PSERROR_Deserialize_ScriptError("JS_GetClassObject failed"); 337 306 338 JSObject* obj = JS_New(cx, ctorobj, 1, &val);307 JSObject* obj = JS_New(cx, ctorobj, 1, val.address()); 339 308 if (!obj) 340 309 throw PSERROR_Deserialize_ScriptError("JS_New failed"); 341 310 AddScriptBackref(obj); … … 354 323 355 324 // Get buffer object 356 325 jsval bufferVal = ReadScriptVal("buffer", NULL); 357 CScriptValRooted bufferValRoot(cx, bufferVal);358 326 359 if ( !JSVAL_IS_OBJECT(bufferVal))327 if (JSVAL_IS_PRIMITIVE(bufferVal)) 360 328 throw PSERROR_Deserialize_ScriptError(); 361 329 362 330 JSObject* bufferObj = JSVAL_TO_OBJECT(bufferVal); 363 if (! js_IsArrayBuffer(bufferObj))331 if (!JS_IsArrayBufferObject(bufferObj)) 364 332 throw PSERROR_Deserialize_ScriptError("js_IsArrayBuffer failed"); 365 333 366 JSObject* arrayObj = js_CreateTypedArrayWithBuffer(cx, GetJSArrayType(arrayType), bufferObj, byteOffset, length); 334 JSObject* arrayObj; 335 switch(arrayType) 336 { 337 case SCRIPT_TYPED_ARRAY_INT8: 338 arrayObj = JS_NewInt8ArrayWithBuffer(cx, bufferObj, byteOffset, length); 339 break; 340 case SCRIPT_TYPED_ARRAY_UINT8: 341 arrayObj = JS_NewUint8ArrayWithBuffer(cx, bufferObj, byteOffset, length); 342 break; 343 case SCRIPT_TYPED_ARRAY_INT16: 344 arrayObj = JS_NewInt16ArrayWithBuffer(cx, bufferObj, byteOffset, length); 345 break; 346 case SCRIPT_TYPED_ARRAY_UINT16: 347 arrayObj = JS_NewUint16ArrayWithBuffer(cx, bufferObj, byteOffset, length); 348 break; 349 case SCRIPT_TYPED_ARRAY_INT32: 350 arrayObj = JS_NewInt32ArrayWithBuffer(cx, bufferObj, byteOffset, length); 351 break; 352 case SCRIPT_TYPED_ARRAY_UINT32: 353 arrayObj = JS_NewUint32ArrayWithBuffer(cx, bufferObj, byteOffset, length); 354 break; 355 case SCRIPT_TYPED_ARRAY_FLOAT32: 356 arrayObj = JS_NewFloat32ArrayWithBuffer(cx, bufferObj, byteOffset, length); 357 break; 358 case SCRIPT_TYPED_ARRAY_FLOAT64: 359 arrayObj = JS_NewFloat64ArrayWithBuffer(cx, bufferObj, byteOffset, length); 360 break; 361 case SCRIPT_TYPED_ARRAY_UINT8_CLAMPED: 362 arrayObj = JS_NewUint8ClampedArrayWithBuffer(cx, bufferObj, byteOffset, length); 363 break; 364 default: 365 throw PSERROR_Deserialize_ScriptError("Failed to deserialize unrecognized typed array view"); 366 } 367 367 if (!arrayObj) 368 368 throw PSERROR_Deserialize_ScriptError("js_CreateTypedArrayWithBuffer failed"); 369 369 … … 383 383 #error TODO: need to convert JS ArrayBuffer data from little-endian 384 384 #endif 385 385 386 JSObject* bufferObj = js_CreateArrayBuffer(cx, length); 387 if (!bufferObj) 388 throw PSERROR_Deserialize_ScriptError("js_CreateArrayBuffer failed"); 389 386 JSObject* bufferObj = JS_NewArrayBufferWithContents(cx, (void*)bufferData); 390 387 AddScriptBackref(bufferObj); 391 388 392 js::ArrayBuffer* buffer = js::ArrayBuffer::fromJSObject(bufferObj);393 memcpy(buffer->data, bufferData, length);394 delete[] bufferData;395 396 389 return OBJECT_TO_JSVAL(bufferObj); 397 390 } 398 391 default: … … 440 433 441 434 void CStdDeserializer::ScriptObjectAppend(const char* name, jsval& obj) 442 435 { 443 if ( !JSVAL_IS_OBJECT(obj))436 if (JSVAL_IS_PRIMITIVE(obj)) 444 437 throw PSERROR_Deserialize_ScriptError(); 445 438 446 439 ReadScriptVal(name, JSVAL_TO_OBJECT(obj)); -
source/simulation2/serialization/BinarySerializer.cpp
27 27 #include "scriptinterface/ScriptInterface.h" 28 28 #include "scriptinterface/ScriptExtraHeaders.h" // for JSDOUBLE_IS_INT32, typed arrays 29 29 30 static u8 GetArrayType( uint32arrayType)30 static u8 GetArrayType(JSArrayBufferViewType arrayType) 31 31 { 32 32 switch(arrayType) 33 33 { 34 case js::TypedArray::TYPE_INT8:34 case JSArrayBufferViewType::TYPE_INT8: 35 35 return SCRIPT_TYPED_ARRAY_INT8; 36 case js::TypedArray::TYPE_UINT8:36 case JSArrayBufferViewType::TYPE_UINT8: 37 37 return SCRIPT_TYPED_ARRAY_UINT8; 38 case js::TypedArray::TYPE_INT16:38 case JSArrayBufferViewType::TYPE_INT16: 39 39 return SCRIPT_TYPED_ARRAY_INT16; 40 case js::TypedArray::TYPE_UINT16:40 case JSArrayBufferViewType::TYPE_UINT16: 41 41 return SCRIPT_TYPED_ARRAY_UINT16; 42 case js::TypedArray::TYPE_INT32:42 case JSArrayBufferViewType::TYPE_INT32: 43 43 return SCRIPT_TYPED_ARRAY_INT32; 44 case js::TypedArray::TYPE_UINT32:44 case JSArrayBufferViewType::TYPE_UINT32: 45 45 return SCRIPT_TYPED_ARRAY_UINT32; 46 case js::TypedArray::TYPE_FLOAT32:46 case JSArrayBufferViewType::TYPE_FLOAT32: 47 47 return SCRIPT_TYPED_ARRAY_FLOAT32; 48 case js::TypedArray::TYPE_FLOAT64:48 case JSArrayBufferViewType::TYPE_FLOAT64: 49 49 return SCRIPT_TYPED_ARRAY_FLOAT64; 50 case js::TypedArray::TYPE_UINT8_CLAMPED:50 case JSArrayBufferViewType::TYPE_UINT8_CLAMPED: 51 51 return SCRIPT_TYPED_ARRAY_UINT8_CLAMPED; 52 52 default: 53 53 LOGERROR(L"Cannot serialize unrecognized typed array view: %d", arrayType); … … 60 60 m_ScriptBackrefsArena(1 * MiB), m_ScriptBackrefs(backrefs_t::key_compare(), ScriptBackrefsAlloc(m_ScriptBackrefsArena)), m_ScriptBackrefsNext(1) 61 61 { 62 62 } 63 63 // TODO YGW: Test serialization... 64 64 void CBinarySerializerScriptImpl::HandleScriptVal(jsval val) 65 65 { 66 66 JSContext* cx = m_ScriptInterface.GetContext(); 67 JSAutoRequest rq(cx); 67 68 68 69 switch (JS_TypeOfValue(cx, val)) 69 70 { … … 85 86 break; 86 87 } 87 88 88 JSObject* obj = JSVAL_TO_OBJECT(val); 89 //JSObject* obj = JSVAL_TO_OBJECT(val); 90 JS::RootedObject obj(cx, JSVAL_TO_OBJECT(val)); 89 91 90 92 // If we've already serialized this object, just output a reference to it 91 93 u32 tag = GetScriptBackrefTag(obj); … … 104 106 105 107 // Arrays like [1, 2, ] have an 'undefined' at the end which is part of the 106 108 // length but seemingly isn't enumerated, so store the length explicitly 107 jsuint length = 0;109 uint length = 0; 108 110 if (!JS_GetArrayLength(cx, obj, &length)) 109 111 throw PSERROR_Serialize_ScriptError("JS_GetArrayLength failed"); 110 112 m_Serializer.NumberU32_Unbounded("array length", length); 111 113 } 112 else if (js_IsTypedArray(obj)) 114 //JS_IsArrayBufferViewObject() 115 //JS_IsTypedArrayObject() 116 else if (JS_IsTypedArrayObject(obj)) 113 117 { 114 118 m_Serializer.NumberU8_Unbounded("type", SCRIPT_TYPE_TYPED_ARRAY); 115 119 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); 120 m_Serializer.NumberU8_Unbounded("array type", GetArrayType(JS_GetArrayBufferViewType(obj))); 121 m_Serializer.NumberU32_Unbounded("byte offset", JS_GetTypedArrayByteOffset(obj)); 122 m_Serializer.NumberU32_Unbounded("length", JS_GetTypedArrayLength(obj)); 121 123 122 124 // Now handle its array buffer 123 125 // this may be a backref, since ArrayBuffers can be shared by multiple views 124 HandleScriptVal(OBJECT_TO_JSVAL( typedArray->bufferJS));126 HandleScriptVal(OBJECT_TO_JSVAL(JS_GetArrayBufferViewBuffer(obj))); 125 127 break; 126 128 } 127 else if ( js_IsArrayBuffer(obj))129 else if (JS_IsArrayBufferObject(obj)) 128 130 { 129 131 m_Serializer.NumberU8_Unbounded("type", SCRIPT_TYPE_ARRAY_BUFFER); 130 132 131 js::ArrayBuffer* arrayBuffer = js::ArrayBuffer::fromJSObject(obj);132 133 133 #if BYTE_ORDER != LITTLE_ENDIAN 134 134 #error TODO: need to convert JS ArrayBuffer data to little-endian 135 135 #endif 136 136 137 u32 length = arrayBuffer->byteLength;137 u32 length = JS_GetArrayBufferByteLength(obj); 138 138 m_Serializer.NumberU32_Unbounded("buffer length", length); 139 m_Serializer.RawBytes("buffer data", (const u8*) arrayBuffer->data, length);139 m_Serializer.RawBytes("buffer data", (const u8*)JS_GetArrayBufferData(obj), length); 140 140 break; 141 141 } 142 142 else 143 143 { 144 144 // Find type of object 145 JSClass* jsclass = JS_G ET_CLASS(cx,obj);145 JSClass* jsclass = JS_GetClass(obj); 146 146 if (!jsclass) 147 throw PSERROR_Serialize_ScriptError("JS_G ET_CLASSfailed");147 throw PSERROR_Serialize_ScriptError("JS_GetClass failed"); 148 148 JSProtoKey protokey = JSCLASS_CACHED_PROTO_KEY(jsclass); 149 149 150 150 if (protokey == JSProto_Object) 151 151 { 152 152 // Object class - check for user-defined prototype 153 JSObject* proto = JS_GetPrototype(cx, obj); 153 JS::RootedObject proto(cx); 154 JS_GetPrototype(cx, obj, &proto); 154 155 if (!proto) 155 156 throw PSERROR_Serialize_ScriptError("JS_GetPrototype failed"); 156 157 … … 172 173 173 174 // Does it have custom Serialize function? 174 175 // if so, we serialize the data it returns, rather than the object's properties directly 175 JSBool hasCustomSerialize;176 bool hasCustomSerialize; 176 177 if (!JS_HasProperty(cx, obj, "Serialize", &hasCustomSerialize)) 177 178 throw PSERROR_Serialize_ScriptError("JS_HasProperty failed"); 178 179 179 180 if (hasCustomSerialize) 180 181 { 181 jsval serialize;182 JS::RootedValue serialize(cx); 182 183 if (!JS_LookupProperty(cx, obj, "Serialize", &serialize)) 183 184 throw PSERROR_Serialize_ScriptError("JS_LookupProperty failed"); 184 185 … … 199 200 // Standard Number object 200 201 m_Serializer.NumberU8_Unbounded("type", SCRIPT_TYPE_OBJECT_NUMBER); 201 202 // Get primitive value 202 jsdouble d;203 double d; 203 204 if (!JS_ValueToNumber(cx, val, &d)) 204 205 throw PSERROR_Serialize_ScriptError("JS_ValueToNumber failed"); 205 206 m_Serializer.NumberDouble_Unbounded("value", d); … … 221 222 // Standard Boolean object 222 223 m_Serializer.NumberU8_Unbounded("type", SCRIPT_TYPE_OBJECT_BOOLEAN); 223 224 // Get primitive value 224 JSBool b;225 bool b; 225 226 if (!JS_ValueToBoolean(cx, val, &b)) 226 227 throw PSERROR_Serialize_ScriptError("JS_ValueToBoolean failed"); 227 m_Serializer.Bool("value", b == JS_TRUE);228 m_Serializer.Bool("value", b); 228 229 break; 229 230 } 230 231 else … … 240 241 // (Note that we don't do any rooting, because we assume nothing is going to trigger GC. 241 242 // I'm not absolute certain that's necessarily a valid assumption.) 242 243 243 AutoJSIdArray ida (cx, JS_Enumerate(cx, obj));244 if (!ida .get())244 JS::AutoIdArray ida (cx, JS_Enumerate(cx, obj)); 245 if (!ida) 245 246 throw PSERROR_Serialize_ScriptError("JS_Enumerate failed"); 246 247 247 248 m_Serializer.NumberU32_Unbounded("num props", (uint32_t)ida.length()); … … 250 251 { 251 252 jsid id = ida[i]; 252 253 253 jsval idval, propval; 254 JS::Value idval; 255 JS::RootedValue propval(cx); 254 256 255 257 // Get the property name as a string 256 258 if (!JS_IdToValue(cx, id, &idval)) … … 308 310 else 309 311 { 310 312 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 } 313 m_Serializer.NumberU8_Unbounded("type", SCRIPT_TYPE_DOUBLE); 314 m_Serializer.NumberDouble_Unbounded("value", JSVAL_TO_DOUBLE(val)); 326 315 } 327 316 break; 328 317 } 329 318 case JSTYPE_BOOLEAN: 330 319 { 331 320 m_Serializer.NumberU8_Unbounded("type", SCRIPT_TYPE_BOOLEAN); 332 JSBool b = JSVAL_TO_BOOLEAN(val);321 bool b = JSVAL_TO_BOOLEAN(val); 333 322 m_Serializer.NumberU8_Unbounded("value", b ? 1 : 0); 334 323 break; 335 324 } 336 case JSTYPE_XML:337 {338 LOGERROR(L"Cannot serialise JS objects of type 'xml'");339 throw PSERROR_Serialize_InvalidScriptValue();340 }341 325 default: 342 326 { 343 327 debug_warn(L"Invalid TypeOfValue"); … … 349 333 void CBinarySerializerScriptImpl::ScriptString(const char* name, JSString* string) 350 334 { 351 335 JSContext* cx = m_ScriptInterface.GetContext(); 336 JSAutoRequest rq(cx); 337 352 338 size_t length; 353 339 const jschar* chars = JS_GetStringCharsAndLength(cx, string, &length); 354 340 … … 382 368 383 369 // If it was newly inserted, we need to make sure it gets rooted 384 370 // for the duration that it's in m_ScriptBackrefs 371 // Note: Spidermonkey has a moving GC. JSObject pointers in this mapping table can change, 372 // but we have registered a custom trace call for the time m_ScriptBackrefs is alive which 373 // takes care of updating the pointers in our mapping table. 374 // TODO: Could this be bad for GC-Performance if we serialize large objects and keep the Serializer 375 // (including m_ScriptBackrefs) alive? Do we keep it alive somewhere? 385 376 m_Rooter.Push(it.first->first); 386 377 m_ScriptBackrefsNext++; 387 378 // Return a non-tag number so callers know they need to serialize the object -
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 scriptInterface.EnumeratePropertyNamesWithPrefix(JS::RootedObject(scriptInterface.GetContext(), JSVAL_TO_OBJECT(dataval)), "", properties); 333 333 for (std::vector<int>::size_type i = 0; i != properties.size(); i++) 334 334 { 335 335 std::wstring value; -
source/scriptinterface/ScriptConversions.cpp
32 32 33 33 template<> bool ScriptInterface::FromJSVal<bool>(JSContext* cx, jsval v, bool& out) 34 34 { 35 JSBool ret; 35 JSAutoRequest rq(cx); 36 bool ret; 36 37 WARN_IF_NOT(JSVAL_IS_BOOLEAN(v), v); 37 38 if (!JS_ValueToBoolean(cx, v, &ret)) 38 39 return false; … … 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 245 if(!JS_GetProperty(cx, obj, "player", &player) || !FromJSVal(cx, player, out.playerID)) … … 236 266 237 267 template<> jsval ScriptInterface::ToJSVal<float>(JSContext* 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 273 template<> jsval ScriptInterface::ToJSVal<double>(JSContext* 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 … … 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); 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;420 JS::RootedValue el(cx); 389 421 if (!JS_GetElement(cx, obj, i, &el)) 390 422 FAIL("Failed to read array element"); 391 423 T el2; -
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, uintNargc, jsval* vp);54 static bool 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, uintNargc, jsval* vp);61 static bool 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/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, uintNargc, jsval* vp) { \94 bool 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, uintNargc, jsval* vp) { \109 bool 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/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
40 40 41 41 for (size_t i = 0; i < m_Objects.size(); ++i) 42 42 { 43 JS_C ALL_OBJECT_TRACER(trc,m_Objects[i], "AutoGCRooter object");43 JS_CallObjectTracer(trc, &m_Objects[i], "AutoGCRooter object"); 44 44 } 45 45 46 46 for (size_t i = 0; i < m_Vals.size(); ++i) 47 47 { 48 JS_C ALL_VALUE_TRACER(trc,m_Vals[i], "AutoGCRooter val");48 JS_CallValueTracer(trc, &m_Vals[i], "AutoGCRooter val"); 49 49 } 50 50 51 JSContext* cx = m_ScriptInterface.GetContext(); 51 52 for (size_t i = 0; i < m_IdArrays.size(); ++i) 52 53 { 53 for ( jsint j = 0; j < m_IdArrays[i]->length; ++j)54 for (size_t j = 0; j < JS_IdArrayLength(cx, m_IdArrays[i]); ++j) 54 55 { 55 56 jsval val = JSVAL_VOID; 56 JS_IdToValue( m_ScriptInterface.GetContext(), m_IdArrays[i]->vector[j], &val);57 JS_C ALL_VALUE_TRACER(trc,val, "AutoGCRooter id array");57 JS_IdToValue(cx, JS_IdArrayGet(cx, m_IdArrays[i], j), &val); 58 JS_CallValueTracer(trc, &val, "AutoGCRooter id array"); 58 59 } 59 60 } 60 61 -
source/scriptinterface/ScriptInterface.h
25 25 #include "ScriptTypes.h" 26 26 #include "ScriptVal.h" 27 27 28 #include "js /jsapi.h"28 #include "jsapi.h" 29 29 30 30 #include "ps/Errors.h" 31 31 ERROR_GROUP(Scripting); … … 114 114 void* pCBData; // meant to be used as the "this" object for callback functions 115 115 } m_CxPrivate; 116 116 117 void Tick(); 117 118 void SetCallbackData(void* pCBData); 118 119 static CxPrivate* GetScriptInterfaceAndCBData(JSContext* cx); 119 120 … … 136 137 * Call a constructor function, equivalent to JS "new ctor(arg)". 137 138 * @return The new object; or JSVAL_VOID on failure, and logs an error message 138 139 */ 139 jsval CallConstructor(jsval ctor, jsval arg);140 jsval CallConstructor(jsval ctor, int argc, jsval argv); 140 141 141 142 /** 142 143 * Create an object as with CallConstructor except don't actually execute the … … 251 252 */ 252 253 bool HasProperty(jsval obj, const char* name); 253 254 254 bool EnumeratePropertyNamesWithPrefix( jsvalobj, const char* prefix, std::vector<std::string>& out);255 bool EnumeratePropertyNamesWithPrefix(JS::HandleObject obj, const char* prefix, std::vector<std::string>& out); 255 256 256 bool SetPrototype( jsval obj, jsvalproto);257 bool SetPrototype(JS::HandleObject obj, JS::HandleObject proto); 257 258 258 259 bool FreezeObject(jsval obj, bool deep); 259 260 … … 338 339 */ 339 340 void MaybeGC(); 340 341 342 bool MathRandom(double& nbr); 343 341 344 /** 342 345 * Structured clones are a way to serialize 'simple' JS values into a buffer 343 346 * that can safely be passed between contexts and runtimes and threads. … … 351 354 public: 352 355 StructuredClone(); 353 356 ~StructuredClone(); 354 JSContext* m_Context; 355 uint64* m_Data; 357 uint64_t* m_Data; 356 358 size_t m_Size; 357 359 }; 358 360 … … 367 369 bool SetProperty_(jsval obj, const char* name, jsval value, bool readonly, bool enumerate); 368 370 bool SetProperty_(jsval obj, const wchar_t* name, jsval value, bool readonly, bool enumerate); 369 371 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);372 bool GetProperty_(jsval obj, const char* name, JS::MutableHandleValue out); 373 bool GetPropertyInt_(jsval obj, int name, JS::MutableHandleValue value); 372 374 static bool IsExceptionPending(JSContext* cx); 373 static JSClass* GetClass(JS Context* cx, JSObject* obj);374 static void* GetPrivate(JS Context* cx, JSObject* obj);375 static JSClass* GetClass(JSObject* obj); 376 static void* GetPrivate(JSObject* obj); 375 377 376 378 class CustomType 377 379 { … … 383 385 void Register(const char* name, JSNative fptr, size_t nargs); 384 386 std::auto_ptr<ScriptInterface_impl> m; 385 387 388 boost::rand48* m_rng; 386 389 std::map<std::string, CustomType> m_CustomObjectTypes; 387 390 388 391 // The nasty macro/template bits are split into a separate file so you don't have to look at them … … 527 530 template<typename T> 528 531 bool ScriptInterface::GetProperty(jsval obj, const char* name, T& out) 529 532 { 530 jsval val; 531 if (! GetProperty_(obj, name, val)) 533 JSContext* cx = GetContext(); 534 JSAutoRequest rq(cx); 535 JS::RootedValue val(cx); 536 if (! GetProperty_(obj, name, &val)) 532 537 return false; 533 return FromJSVal( GetContext(), val, out);538 return FromJSVal(cx, val, out); 534 539 } 535 540 536 541 template<typename T> 537 542 bool ScriptInterface::GetPropertyInt(jsval obj, int name, T& out) 538 543 { 539 jsval val;540 if (! GetPropertyInt_(obj, name, val))544 JS::RootedValue val(GetContext()); 545 if (! GetPropertyInt_(obj, name, &val)) 541 546 return false; 542 547 return FromJSVal(GetContext(), val, out); 543 548 } -
source/scriptinterface/ScriptTypes.h
78 78 # pragma warning(disable:4100) // "unreferenced formal parameter" 79 79 #endif 80 80 81 #include "js/jsapi.h" 81 #include "jsapi.h" 82 #include "jspubtd.h" 82 83 83 84 #if MSC_VERSION 84 85 # pragma warning(pop) … … 88 89 # pragma GCC diagnostic warning "-Wredundant-decls" 89 90 #endif 90 91 91 #if JS_VERSION != 185 92 #error Your compiler is trying to use an incorrect version of the SpiderMonkey library.93 #error The only version that works is the one in the libraries/spidermonkey/ directory,94 #error and it will not work with a typical system-installed version.95 #error Make sure you have got all the right files and include paths.96 #endif92 //#if MOZJS_MAJOR_VERSION != 24 || MOZJS_MINOR_VERSION != 0 93 //#error Your compiler is trying to use an incorrect version of the SpiderMonkey library. 94 //#error The only version that works is the one in the libraries/spidermonkey/ directory, 95 //#error and it will not work with a typical system-installed version. 96 //#error Make sure you have got all the right files and include paths. 97 //#endif 97 98 98 99 class ScriptInterface; 99 100 class CScriptVal; -
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 #include "jsapi.h" 24 #include "jspubtd.h" 25 //#include "jsatom.h" 23 26 27 24 28 struct Unrooter 25 29 { 26 30 Unrooter(JSContext* cx) : cx(cx) { } 27 void operator()(jsval* p) { JS_RemoveValueRoot(cx, p); delete p; } 31 void operator()(jsval* p) 32 { 33 JSAutoRequest rq(cx); 34 JS_RemoveValueRoot(cx, p); delete p; 35 } 28 36 JSContext* cx; 29 37 }; 30 38 31 39 CScriptValRooted::CScriptValRooted(JSContext* cx, jsval val) 32 40 { 41 JSAutoRequest rq(cx); 33 42 jsval* p = new jsval(val); 34 43 JS_AddNamedValueRoot(cx, p, "CScriptValRooted"); 35 44 m_Val = boost::shared_ptr<jsval>(p, Unrooter(cx)); … … 37 46 38 47 CScriptValRooted::CScriptValRooted(JSContext* cx, CScriptVal val) 39 48 { 49 JSAutoRequest rq(cx); 40 50 jsval* p = new jsval(val.get()); 41 51 JS_AddNamedValueRoot(cx, p, "CScriptValRooted"); 42 52 m_Val = boost::shared_ptr<jsval>(p, Unrooter(cx)); … … 49 59 return *m_Val; 50 60 } 51 61 62 void CScriptValRooted::getPtr(JS::Value** val) 63 { 64 *val = &*m_Val; 65 } 66 52 67 jsval& CScriptValRooted::getRef() const 53 68 { 54 69 ENSURE(m_Val); … … 65 80 return !m_Val; 66 81 } 67 82 83 /* 68 84 AutoJSIdArray::AutoJSIdArray(JSContext* cx, JSIdArray* ida) : 69 85 m_Context(cx), m_IdArray(ida) 70 86 { … … 85 101 { 86 102 if (!m_IdArray) 87 103 return 0; 88 return m_IdArray->length;104 return JS_IdArrayLength(m_Context, m_IdArray); 89 105 } 90 106 91 107 jsid AutoJSIdArray::operator[](size_t i) const … … 93 109 if (!(m_IdArray && i < (size_t)m_IdArray->length)) 94 110 return JSID_VOID; 95 111 return m_IdArray->vector[i]; 96 } 112 }*/ 113 114 115 //CRootedWrapper::CRootedWrapper(JSContext* cx, JS::Value val) 116 //{ 117 // JSAutoRequest rq(cx); 118 // JS::Value* wrap = &val; 119 // JS_WrapValue(cx, val); 120 // m_Val = boost::shared_ptr<JS::Value>(wrap, Unrooter(cx)); 121 //} -
source/scriptinterface/ScriptExtraHeaders.h
46 46 # define signbit std::signbit 47 47 #endif 48 48 49 #include "js/jstypedarray.h" 50 #include "js/jsdbgapi.h" 49 //#include "js/jstypedarray.h" 50 //#include "jspubtd.h" 51 //#include "jsatom.h" 52 #include "jsfriendapi.h" 53 #include "js/OldDebugAPI.h" 54 #include "js/StructuredClone.h" 51 55 52 56 #undef signbit 53 57 -
source/scriptinterface/ScriptStats.cpp
21 21 22 22 #include "scriptinterface/ScriptInterface.h" 23 23 24 #include "js /jsapi.h"24 #include "jsapi.h" 25 25 26 26 CScriptStatsTable* g_ScriptStatsTable; 27 27 -
source/scriptinterface/ScriptInterface.cpp
71 71 ScriptRuntime(int runtimeSize) : 72 72 m_rooter(NULL) 73 73 { 74 m_rt = JS_NewRuntime(runtimeSize); 74 // TODO: check what JS_Init() actually does and what the constraints are 75 // What I know: It must be called before calling JS_NewRuntime 76 JS_Init(); 77 m_rt = JS_NewRuntime(runtimeSize, JS_USE_HELPER_THREADS); 78 75 79 ENSURE(m_rt); // TODO: error handling 76 80 81 JS_SetNativeStackQuota(m_rt, 128 * sizeof(size_t) * 1024); 77 82 if (g_ScriptProfilingEnabled) 78 83 { 79 84 // Profiler isn't thread-safe, so only enable this on the main thread … … 87 92 } 88 93 } 89 94 90 JS_SetExtraGCRoots(m_rt, jshook_trace, this); 95 JS_AddExtraGCRootsTracer(m_rt, jshook_trace, this); 96 m_dummyContext = JS_NewContext(m_rt, STACK_CHUNK_SIZE); 97 ENSURE(m_dummyContext); 91 98 } 92 99 93 100 ~ScriptRuntime() 94 101 { 102 JS_DestroyContext(m_dummyContext); 95 103 JS_DestroyRuntime(m_rt); 96 104 } 97 105 106 JSContext* m_dummyContext; 98 107 JSRuntime* m_rt; 99 108 AutoGCRooter* m_rooter; 100 109 101 110 private: 102 111 103 112 104 static void* jshook_script(JSContext* UNUSED(cx), JS StackFrame* UNUSED(fp), JSBool before, JSBool* UNUSED(ok), void* closure)113 static void* jshook_script(JSContext* UNUSED(cx), JSAbstractFramePtr UNUSED(fp), bool isConstructing, bool before, bool* UNUSED(ok), void* closure) 105 114 { 106 115 if (before) 107 116 g_Profiler.StartScript("script invocation"); … … 154 163 if (slash != filename.npos) 155 164 filename = filename.substr(slash+1); 156 165 157 uint Nline = JS_PCToLineNumber(cx, script, pc);166 uint line = JS_PCToLineNumber(cx, script, pc); 158 167 159 168 std::stringstream ss; 160 169 ss << "(" << filename << ":" << line << ")"; … … 178 187 boost::flyweights::no_locking 179 188 > LocFlyweight; 180 189 181 static void* jshook_function(JSContext* cx, JS StackFrame* fp, JSBool before, JSBool* UNUSED(ok), void* closure)190 static void* jshook_function(JSContext* cx, JSAbstractFramePtr fp, bool isConstructing, bool before, bool* UNUSED(ok), void* closure) 182 191 { 183 192 if (!before) 184 193 { … … 186 195 return closure; 187 196 } 188 197 189 JSFunction* fn = JS_GetFrameFunction(cx, fp);198 JSFunction* fn = fp.maybeFun(); 190 199 if (!fn) 191 200 { 192 201 g_Profiler.StartScript("(function)"); … … 207 216 } 208 217 209 218 // No name - compute from the location instead 210 ScriptLocation loc = { cx, JS_GetFrameScript(cx, fp), JS_GetFramePC(cx, fp) }; 219 JSScript* script; 220 unsigned lineno; 221 JS_DescribeScriptedCaller(cx, &script, &lineno); 222 ENSURE(script == fp.script()); 223 ScriptLocation loc = { cx, fp.script(), JS_LineNumberToPC(cx, script, lineno) }; 211 224 g_Profiler.StartScript(LocFlyweight(loc).get().name.c_str()); 212 225 213 226 return closure; … … 233 246 { 234 247 ScriptInterface_impl(const char* nativeScopeName, const shared_ptr<ScriptRuntime>& runtime); 235 248 ~ScriptInterface_impl(); 236 void Register(const char* name, JSNative fptr, uint Nnargs);249 void Register(const char* name, JSNative fptr, uint nargs); 237 250 238 251 shared_ptr<ScriptRuntime> m_runtime; 239 252 JSContext* m_cx; 240 253 JSObject* m_glob; // global scope object 254 JSCompartment* m_comp; 255 boost::rand48* m_rng; 241 256 JSObject* m_nativeScope; // native function scope object 242 257 }; 243 258 … … 246 261 247 262 JSClass global_class = { 248 263 "global", JSCLASS_GLOBAL_FLAGS, 249 JS_PropertyStub, JS_ PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,250 JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,264 JS_PropertyStub, JS_DeletePropertyStub, JS_PropertyStub, JS_StrictPropertyStub, 265 JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, 251 266 NULL, NULL, NULL, NULL, 252 267 NULL, NULL, NULL, NULL 253 268 }; 254 269 255 270 void ErrorReporter(JSContext* cx, const char* message, JSErrorReport* report) 256 271 { 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 272 263 273 std::stringstream msg; 264 274 bool isWarning = JSREPORT_IS_WARNING(report->flags); … … 273 283 274 284 // If there is an exception, then print its stack trace 275 285 jsval excn; 276 if (JS_GetPendingException(cx, &excn) && JSVAL_IS_OBJECT(excn))286 if (JS_GetPendingException(cx, &excn) && !JSVAL_IS_PRIMITIVE(excn)) 277 287 { 278 288 // TODO: this violates the docs ("The error reporter callback must not reenter the JSAPI.") 279 289 … … 309 319 310 320 // Functions in the global namespace: 311 321 312 JSBool print(JSContext* cx, uintNargc, jsval* vp)322 bool print(JSContext* cx, uint argc, jsval* vp) 313 323 { 314 for (uint Ni = 0; i < argc; ++i)324 for (uint i = 0; i < argc; ++i) 315 325 { 316 326 std::wstring str; 317 327 if (!ScriptInterface::FromJSVal(cx, JS_ARGV(cx, vp)[i], str)) 318 return JS_FALSE;328 return false; 319 329 debug_printf(L"%ls", str.c_str()); 320 330 } 321 331 fflush(stdout); 322 332 JS_SET_RVAL(cx, vp, JSVAL_VOID); 323 return JS_TRUE;333 return true; 324 334 } 325 335 326 JSBool logmsg(JSContext* cx, uintNargc, jsval* vp)336 bool logmsg(JSContext* cx, uint argc, jsval* vp) 327 337 { 328 338 if (argc < 1) 329 339 { 330 340 JS_SET_RVAL(cx, vp, JSVAL_VOID); 331 return JS_TRUE;341 return true; 332 342 } 333 343 334 344 std::wstring str; 335 345 if (!ScriptInterface::FromJSVal(cx, JS_ARGV(cx, vp)[0], str)) 336 return JS_FALSE;337 LOGMESSAGE(L"%ls ", str.c_str());346 return false; 347 LOGMESSAGE(L"%ls%f", str.c_str(), timer_Time()); 338 348 JS_SET_RVAL(cx, vp, JSVAL_VOID); 339 return JS_TRUE;349 return true; 340 350 } 341 351 342 JSBool warn(JSContext* cx, uintNargc, jsval* vp)352 bool warn(JSContext* cx, uint argc, jsval* vp) 343 353 { 344 354 if (argc < 1) 345 355 { 346 356 JS_SET_RVAL(cx, vp, JSVAL_VOID); 347 return JS_TRUE;357 return true; 348 358 } 349 359 350 360 std::wstring str; 351 361 if (!ScriptInterface::FromJSVal(cx, JS_ARGV(cx, vp)[0], str)) 352 return JS_FALSE;362 return false; 353 363 LOGWARNING(L"%ls", str.c_str()); 354 364 JS_SET_RVAL(cx, vp, JSVAL_VOID); 355 return JS_TRUE;365 return true; 356 366 } 357 367 358 JSBool error(JSContext* cx, uintNargc, jsval* vp)368 bool error(JSContext* cx, uint argc, jsval* vp) 359 369 { 360 370 if (argc < 1) 361 371 { 362 372 JS_SET_RVAL(cx, vp, JSVAL_VOID); 363 return JS_TRUE;373 return true; 364 374 } 365 375 366 376 std::wstring str; 367 377 if (!ScriptInterface::FromJSVal(cx, JS_ARGV(cx, vp)[0], str)) 368 return JS_FALSE;378 return false; 369 379 LOGERROR(L"%ls", str.c_str()); 370 380 JS_SET_RVAL(cx, vp, JSVAL_VOID); 371 return JS_TRUE;381 return true; 372 382 } 373 383 374 JSBool deepcopy(JSContext* cx, uintNargc, jsval* vp)384 bool deepcopy(JSContext* cx, uint argc, jsval* vp) 375 385 { 376 386 if (argc < 1) 377 387 { 378 388 JS_SET_RVAL(cx, vp, JSVAL_VOID); 379 return JS_TRUE;389 return true; 380 390 } 381 391 382 392 jsval ret; 383 393 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)) 392 return JS_FALSE; 394 if (!JS_StructuredClone(cx, JS_ARGV(cx, vp)[0], &ret, NULL, NULL)) 395 return false; 393 396 394 397 JS_SET_RVAL(cx, vp, ret); 395 return JS_TRUE;398 return true; 396 399 } 397 400 398 JSBool ProfileStart(JSContext* cx, uintNargc, jsval* vp)401 bool ProfileStart(JSContext* cx, uint argc, jsval* vp) 399 402 { 400 403 const char* name = "(ProfileStart)"; 401 404 … … 403 406 { 404 407 std::string str; 405 408 if (!ScriptInterface::FromJSVal(cx, JS_ARGV(cx, vp)[0], str)) 406 return JS_FALSE;409 return false; 407 410 408 411 typedef boost::flyweight< 409 412 std::string, … … 420 423 g_Profiler2.RecordRegionEnter(name); 421 424 422 425 JS_SET_RVAL(cx, vp, JSVAL_VOID); 423 return JS_TRUE;426 return true; 424 427 } 425 428 426 JSBool ProfileStop(JSContext* UNUSED(cx), uintNUNUSED(argc), jsval* vp)429 bool ProfileStop(JSContext* UNUSED(cx), uint UNUSED(argc), jsval* vp) 427 430 { 428 431 if (CProfileManager::IsInitialised() && ThreadUtil::IsMainThread()) 429 432 g_Profiler.Stop(); … … 431 434 g_Profiler2.RecordRegionLeave("(ProfileStop)"); 432 435 433 436 JS_SET_RVAL(cx, vp, JSVAL_VOID); 434 return JS_TRUE;437 return true; 435 438 } 436 439 437 440 // Math override functions: … … 452 455 } 453 456 } 454 457 455 JSBool Math_random(JSContext* cx, uintNUNUSED(argc), jsval* vp)458 bool Math_random(JSContext* cx, uint UNUSED(argc), jsval* vp) 456 459 { 457 // Grab the RNG that was hidden in our slot 458 jsval rngp; 459 if (!JS_GetReservedSlot(cx, JSVAL_TO_OBJECT(JS_CALLEE(cx, vp)), 0, &rngp)) 460 return JS_FALSE; 461 boost::rand48* rng = static_cast<boost::rand48*>(JSVAL_TO_PRIVATE(rngp)); 460 double r; 461 if(!ScriptInterface::GetScriptInterfaceAndCBData(cx)->pScriptInterface->MathRandom(r)) 462 { 463 return false; 464 } 465 else 466 { 467 jsval rv = JS_NumberValue(r); 468 JS_SET_RVAL(cx, vp, rv); 469 return true; 470 } 471 } 462 472 463 double r = generate_uniform_real(*rng, 0.0, 1.0); 473 } // anonymous namespace 464 474 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; 475 bool ScriptInterface::MathRandom(double& nbr) 476 { 477 if (m->m_rng == NULL) 478 return false; 479 nbr = generate_uniform_real(*(m->m_rng), 0.0, 1.0); 480 return true; 470 481 } 471 482 472 } // anonymous namespace473 474 483 ScriptInterface_impl::ScriptInterface_impl(const char* nativeScopeName, const shared_ptr<ScriptRuntime>& runtime) : 475 484 m_runtime(runtime) 476 485 { 477 JSBool ok;486 bool ok; 478 487 479 488 m_cx = JS_NewContext(m_runtime->m_rt, STACK_CHUNK_SIZE); 480 489 ENSURE(m_cx); 481 490 491 JS_SetParallelIonCompilationEnabled(m_cx, true); 492 482 493 // For GC debugging: 483 494 // JS_SetGCZeal(m_cx, 2); 484 495 … … 486 497 487 498 JS_SetErrorReporter(m_cx, ErrorReporter); 488 499 489 uint32 options = 0; 490 options |= JSOPTION_STRICT; // "warn on dubious practice" 491 options |= JSOPTION_XML; // "ECMAScript for XML support: parse <!-- --> as a token" 500 uint32_t options = 0; 501 options |= JSOPTION_EXTRA_WARNINGS; // "warn on dubious practice" 502 // We use strict mode to encourage better coding practices and 503 //to get code that can be optimized better by Spidermonkey's JIT compiler. 504 options |= JSOPTION_STRICT_MODE; 505 //options |= JSOPTION_ALLOW_XML; // "ECMAScript for XML support: parse <!-- --> as a token" 492 506 options |= JSOPTION_VAROBJFIX; // "recommended" (fixes variable scoping) 493 507 494 508 // Enable method JIT, unless script profiling/debugging is enabled (since profiling/debugging … … 496 510 // TODO: Verify what exactly is incompatible 497 511 if (!g_ScriptProfilingEnabled && !g_JSDebuggerEnabled) 498 512 { 499 options |= JSOPTION_METHODJIT; 513 options |= JSOPTION_BASELINE; 514 options |= JSOPTION_ION; 515 options |= JSOPTION_TYPE_INFERENCE; 516 options |= JSOPTION_COMPILE_N_GO; 500 517 501 518 // Some other JIT flags to experiment with: 502 options |= JSOPTION_JIT; 503 options |= JSOPTION_PROFILING; 519 //options |= JSOPTION_METHODJIT_ALWAYS; 504 520 } 505 521 506 522 JS_SetOptions(m_cx, options); 507 JS _SetVersion(m_cx, JSVERSION_LATEST);523 JSAutoRequest rq(m_cx); 508 524 509 m_glob = JS_NewCompartmentAndGlobalObject(m_cx, &global_class, NULL); 525 JS::CompartmentOptions opt; 526 opt.setVersion(JSVERSION_LATEST); 527 JS::RootedObject tmpglob(m_cx, JS_NewGlobalObject(m_cx, &global_class, NULL, JS::OnNewGlobalHookOption::DontFireOnNewGlobalHook, opt)); 528 // TODO: check again if we're doing everything correctly https://bugzilla.mozilla.org/show_bug.cgi?id=897322 529 JS_FireOnNewGlobalObject(m_cx, tmpglob); 530 m_glob = tmpglob.get(); 531 m_comp = JS_EnterCompartment(m_cx, m_glob); 510 532 511 533 ok = JS_InitStandardClasses(m_cx, m_glob); 512 534 ENSURE(ok); … … 529 551 530 552 ScriptInterface_impl::~ScriptInterface_impl() 531 553 { 554 { 555 JSAutoRequest rq(m_cx); 556 JS_LeaveCompartment(m_cx, m_comp); 557 } 532 558 JS_DestroyContext(m_cx); 533 559 } 534 560 535 void ScriptInterface_impl::Register(const char* name, JSNative fptr, uint Nnargs)561 void ScriptInterface_impl::Register(const char* name, JSNative fptr, uint nargs) 536 562 { 563 JSAutoRequest rq(m_cx); 537 564 JSFunction* func = JS_DefineFunction(m_cx, m_nativeScope, name, fptr, nargs, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT); 538 565 539 566 if (!func) … … 552 579 > LockedStringFlyweight; 553 580 554 581 LockedStringFlyweight fw(name); 555 JS_SetReservedSlot( m_cx,JS_GetFunctionObject(func), 0, PRIVATE_TO_JSVAL((void*)fw.get().c_str()));582 JS_SetReservedSlot(JS_GetFunctionObject(func), 0, PRIVATE_TO_JSVAL((void*)fw.get().c_str())); 556 583 } 557 584 } 558 585 … … 599 626 JS_ShutDown(); 600 627 } 601 628 629 void ScriptInterface::Tick() 630 { 631 js::NotifyAnimationActivity(m->m_glob); 632 } 633 602 634 void ScriptInterface::SetCallbackData(void* pCBData) 603 635 { 604 636 m_CxPrivate.pCBData = pCBData; … … 633 665 634 666 bool ScriptInterface::ReplaceNondeterministicRNG(boost::rand48& rng) 635 667 { 636 jsval math; 637 if (JS_GetProperty(m->m_cx, m->m_glob, "Math", &math) && JSVAL_IS_OBJECT(math)) 668 JSAutoRequest rq(m->m_cx); 669 JS::RootedValue math(m->m_cx); 670 if (JS_GetProperty(m->m_cx, m->m_glob, "Math", &math) && !JSVAL_IS_PRIMITIVE(math)) 638 671 { 639 672 JSFunction* random = JS_DefineFunction(m->m_cx, JSVAL_TO_OBJECT(math), "random", Math_random, 0, 640 673 JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT); 641 674 if (random) 642 675 { 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; 676 m->m_rng = &rng; 677 return true; 646 678 } 647 679 } 648 680 … … 652 684 653 685 void ScriptInterface::Register(const char* name, JSNative fptr, size_t nargs) 654 686 { 655 m->Register(name, fptr, (uint N)nargs);687 m->Register(name, fptr, (uint)nargs); 656 688 } 657 689 658 690 JSContext* ScriptInterface::GetContext() const … … 678 710 } 679 711 680 712 681 jsval ScriptInterface::CallConstructor(jsval ctor, jsval arg)713 jsval ScriptInterface::CallConstructor(jsval ctor, int argc, jsval argv) 682 714 { 683 if (!JSVAL_IS_OBJECT(ctor)) 715 JSAutoRequest rq(m->m_cx); 716 if (JSVAL_IS_PRIMITIVE(ctor)) 684 717 { 685 718 LOGERROR(L"CallConstructor: ctor is not an object"); 686 719 return JSVAL_VOID; 687 720 } 688 721 689 return OBJECT_TO_JSVAL(JS_New(m->m_cx, JSVAL_TO_OBJECT(ctor), 1, &arg)); 722 // Passing argc 0 and argv JSVAL_VOID causes a crash in mozjs24 723 if (argc == 0) 724 { 725 return OBJECT_TO_JSVAL(JS_New(m->m_cx, JSVAL_TO_OBJECT(ctor), 0, NULL)); 726 } 727 else 728 return OBJECT_TO_JSVAL(JS_New(m->m_cx, JSVAL_TO_OBJECT(ctor), argc, &argv)); 690 729 } 691 730 692 731 jsval ScriptInterface::NewObjectFromConstructor(jsval ctor) 693 732 { 733 JSAutoRequest rq(m->m_cx); 694 734 // Get the constructor's prototype 695 735 // (Can't use JS_GetPrototype, since we want .prototype not .__proto__) 696 jsval protoVal;736 JS::RootedValue protoVal(m->m_cx); 697 737 if (!JS_GetProperty(m->m_cx, JSVAL_TO_OBJECT(ctor), "prototype", &protoVal)) 698 738 { 699 739 LOGERROR(L"NewObjectFromConstructor: can't get prototype"); 700 740 return JSVAL_VOID; 701 741 } 702 742 703 if ( !JSVAL_IS_OBJECT(protoVal))743 if (JSVAL_IS_PRIMITIVE(protoVal)) 704 744 { 705 745 LOGERROR(L"NewObjectFromConstructor: prototype is not an object"); 706 746 return JSVAL_VOID; 707 747 } 708 748 709 749 JSObject* proto = JSVAL_TO_OBJECT(protoVal); 710 JSObject* parent = JS_GetParent( m->m_cx,JSVAL_TO_OBJECT(ctor));750 JSObject* parent = JS_GetParent(JSVAL_TO_OBJECT(ctor)); 711 751 // TODO: rooting? 712 752 if (!proto || !parent) 713 753 { … … 727 767 728 768 void ScriptInterface::DefineCustomObjectType(JSClass *clasp, JSNative constructor, uint minArgs, JSPropertySpec *ps, JSFunctionSpec *fs, JSPropertySpec *static_ps, JSFunctionSpec *static_fs) 729 769 { 770 JSAutoRequest rq(m->m_cx); 730 771 std::string typeName = clasp->name; 731 772 732 773 if (m_CustomObjectTypes.find(typeName) != m_CustomObjectTypes.end()) … … 774 815 775 816 bool ScriptInterface::CallFunction_(jsval val, const char* name, size_t argc, jsval* argv, jsval& ret) 776 817 { 818 JSAutoRequest rq(m->m_cx); 777 819 JSObject* obj; 778 820 if (!JS_ValueToObject(m->m_cx, val, &obj) || obj == NULL) 779 821 return false; 780 822 781 823 // Check that the named function actually exists, to avoid ugly JS error reports 782 824 // when calling an undefined value 783 JSBool found;825 bool found; 784 826 if (!JS_HasProperty(m->m_cx, obj, name, &found) || !found) 785 827 return false; 786 828 787 JSBool ok = JS_CallFunctionName(m->m_cx, obj, name, (uintN)argc, argv, &ret);829 bool ok = JS_CallFunctionName(m->m_cx, obj, name, (uint)argc, argv, &ret); 788 830 789 return ok ? true : false;831 return ok; 790 832 } 791 833 792 834 jsval ScriptInterface::GetGlobalObject() 793 835 { 794 return OBJECT_TO_JSVAL(JS_GetGlobalObject(m->m_cx)); 836 JSAutoRequest rq(m->m_cx); 837 return OBJECT_TO_JSVAL(JS::CurrentGlobalOrNull(m->m_cx)); 795 838 } 796 839 797 840 JSClass* ScriptInterface::GetGlobalClass() … … 801 844 802 845 bool ScriptInterface::SetGlobal_(const char* name, jsval value, bool replace) 803 846 { 847 JSAutoRequest rq(m->m_cx); 804 848 if (!replace) 805 849 { 806 JSBool found;850 bool found; 807 851 if (!JS_HasProperty(m->m_cx, m->m_glob, name, &found)) 808 852 return false; 809 853 if (found) … … 813 857 } 814 858 } 815 859 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;860 bool ok = JS_DefineProperty(m->m_cx, m->m_glob, name, value, NULL, NULL, JSPROP_ENUMERATE | JSPROP_READONLY 861 | JSPROP_PERMANENT); 862 return ok; 819 863 } 820 864 821 865 bool ScriptInterface::SetProperty_(jsval obj, const char* name, jsval value, bool constant, bool enumerate) 822 866 { 823 uintN attrs = 0; 867 JSAutoRequest rq(m->m_cx); 868 uint attrs = 0; 824 869 if (constant) 825 870 attrs |= JSPROP_READONLY | JSPROP_PERMANENT; 826 871 if (enumerate) 827 872 attrs |= JSPROP_ENUMERATE; 828 873 829 if ( ! JSVAL_IS_OBJECT(obj))874 if (JSVAL_IS_PRIMITIVE(obj)) 830 875 return false; 831 876 JSObject* object = JSVAL_TO_OBJECT(obj); 832 877 … … 837 882 838 883 bool ScriptInterface::SetProperty_(jsval obj, const wchar_t* name, jsval value, bool constant, bool enumerate) 839 884 { 840 uintN attrs = 0; 885 JSAutoRequest rq(m->m_cx); 886 uint attrs = 0; 841 887 if (constant) 842 888 attrs |= JSPROP_READONLY | JSPROP_PERMANENT; 843 889 if (enumerate) 844 890 attrs |= JSPROP_ENUMERATE; 845 891 846 if ( ! JSVAL_IS_OBJECT(obj))892 if ( JSVAL_IS_PRIMITIVE(obj)) 847 893 return false; 848 894 JSObject* object = JSVAL_TO_OBJECT(obj); 849 895 … … 855 901 856 902 bool ScriptInterface::SetPropertyInt_(jsval obj, int name, jsval value, bool constant, bool enumerate) 857 903 { 858 uintN attrs = 0; 904 JSAutoRequest rq(m->m_cx); 905 uint attrs = 0; 859 906 if (constant) 860 907 attrs |= JSPROP_READONLY | JSPROP_PERMANENT; 861 908 if (enumerate) 862 909 attrs |= JSPROP_ENUMERATE; 863 910 864 if ( ! JSVAL_IS_OBJECT(obj))911 if ( JSVAL_IS_PRIMITIVE(obj)) 865 912 return false; 866 913 JSObject* object = JSVAL_TO_OBJECT(obj); 867 914 … … 870 917 return true; 871 918 } 872 919 873 bool ScriptInterface::GetProperty_(jsval obj, const char* name, jsval&out)920 bool ScriptInterface::GetProperty_(jsval obj, const char* name, JS::MutableHandleValue out) 874 921 { 875 if (! JSVAL_IS_OBJECT(obj)) 922 JSAutoRequest rq(m->m_cx); 923 if ( JSVAL_IS_PRIMITIVE(obj)) 876 924 return false; 877 925 JSObject* object = JSVAL_TO_OBJECT(obj); 878 926 879 if (!JS_GetProperty(m->m_cx, object, name, &out))927 if (!JS_GetProperty(m->m_cx, object, name, out)) 880 928 return false; 881 929 return true; 882 930 } 883 931 884 bool ScriptInterface::GetPropertyInt_(jsval obj, int name, jsval&out)932 bool ScriptInterface::GetPropertyInt_(jsval obj, int name, JS::MutableHandleValue out) 885 933 { 886 if (! JSVAL_IS_OBJECT(obj)) 934 JSAutoRequest rq(m->m_cx); 935 if ( JSVAL_IS_PRIMITIVE(obj)) 887 936 return false; 888 937 JSObject* object = JSVAL_TO_OBJECT(obj); 889 938 890 if (!JS_GetPropertyById(m->m_cx, object, INT_TO_JSID(name), &out))939 if (!JS_GetPropertyById(m->m_cx, object, INT_TO_JSID(name), out)) 891 940 return false; 892 941 return true; 893 942 } 894 943 895 944 bool ScriptInterface::HasProperty(jsval obj, const char* name) 896 945 { 897 if (! JSVAL_IS_OBJECT(obj)) 946 // TODO: proper errorhandling 947 JSAutoRequest rq(m->m_cx); 948 if ( JSVAL_IS_PRIMITIVE(obj)) 898 949 return false; 899 950 JSObject* object = JSVAL_TO_OBJECT(obj); 900 951 901 JSBool found;952 bool found; 902 953 if (!JS_HasProperty(m->m_cx, object, name, &found)) 903 954 return false; 904 return (found != JS_FALSE);955 return found; 905 956 } 906 957 907 bool ScriptInterface::EnumeratePropertyNamesWithPrefix( jsvalobj, const char* prefix, std::vector<std::string>& out)958 bool ScriptInterface::EnumeratePropertyNamesWithPrefix(JS::HandleObject obj, const char* prefix, std::vector<std::string>& out) 908 959 { 909 utf16string prefix16 (prefix, prefix+strlen(prefix)); 960 JSAutoRequest rq(m->m_cx); 961 if (obj.get() == 0x0) 962 return true; 910 963 911 if (! JSVAL_IS_OBJECT(obj))912 return false; // TODO: log error messages964 // if ( obj.get().isPrimitive() ) 965 // return false; // TODO: log error messages 913 966 914 JSObject* it = JS_NewPropertyIterator(m->m_cx, JSVAL_TO_OBJECT(obj));967 JSObject* it = JS_NewPropertyIterator(m->m_cx, obj.get()); 915 968 if (!it) 916 969 return false; 917 970 … … 927 980 continue; // ignore integer properties 928 981 929 982 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 983 size_t len = strlen(prefix)+1; 984 char buf[len]; 985 size_t prefixLen = strlen(prefix) * sizeof(char); 986 JS_EncodeStringToBuffer(m->m_cx, name, buf, prefixLen); 987 buf[len-1]= '\0'; 988 if(0 == strcmp(buf, prefix)) 989 { 990 size_t len; 991 const jschar* chars = JS_GetStringCharsAndLength(m->m_cx, name, &len); 992 out.push_back(std::string(chars, chars+len)); 993 } 994 // if (chars && len >= prefix16.size() && memcmp(chars, prefix16.c_str(), prefix16.size()*2) == 0) 995 // out.push_back(std::string(chars, chars+len)); // handles Unicode poorly 996 934 997 } 935 998 936 999 // Recurse up the prototype chain 937 JS Object* prototype = JS_GetPrototype(m->m_cx, JSVAL_TO_OBJECT(obj));938 if ( prototype)1000 JS::RootedObject prototype(m->m_cx); 1001 if (JS_GetPrototype(m->m_cx, obj, &prototype)) 939 1002 { 940 if (! EnumeratePropertyNamesWithPrefix( OBJECT_TO_JSVAL(prototype), prefix, out))1003 if (! EnumeratePropertyNamesWithPrefix(prototype, prefix, out)) 941 1004 return false; 942 1005 } 943 1006 944 1007 return true; 945 1008 } 946 1009 947 bool ScriptInterface::SetPrototype( jsval obj, jsvalproto)1010 bool ScriptInterface::SetPrototype(JS::HandleObject obj, JS::HandleObject proto) 948 1011 { 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; 1012 JSAutoRequest rq(m->m_cx); 1013 //if (JSVAL_IS_PRIMITIVE(obj) || JSVAL_IS_PRIMITIVE(proto)) 1014 // return false; 1015 return JS_SetPrototype(m->m_cx, obj, proto); 952 1016 } 953 1017 954 1018 bool ScriptInterface::FreezeObject(jsval obj, bool deep) 955 1019 { 956 if (!JSVAL_IS_OBJECT(obj)) 1020 JSAutoRequest rq(m->m_cx); 1021 if (JSVAL_IS_PRIMITIVE(obj)) 957 1022 return false; 958 1023 959 1024 if (deep) … … 964 1029 965 1030 bool ScriptInterface::LoadScript(const VfsPath& filename, const std::string& code) 966 1031 { 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 1032 JSAutoRequest rq(m->m_cx); 1033 utf16string codeUtf16(code.begin(), code.end()); 1034 uint lineNo = 1; 972 1035 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 1036 JS::Rooted<JSFunction*> func(m->m_cx, 1037 JS_CompileUCFunction(m->m_cx, m->m_glob, utf8_from_wstring(filename.string()).c_str(), 0, NULL, 1038 reinterpret_cast<const jschar*> (codeUtf16.c_str()), (uint)(codeUtf16.length()), 1039 utf8_from_wstring(filename.string()).c_str(), lineNo) 1040 ); 977 1041 if (!func) 978 1042 return false; 979 1043 980 jsval scriptRval;981 JSBool ok = JS_CallFunction(m->m_cx, NULL, func, 0, NULL, &scriptRval);1044 JS::RootedValue val(m->m_cx); 1045 bool ok = JS_CallFunction(m->m_cx, NULL, func, 0, NULL, val.address()); 982 1046 983 1047 return ok ? true : false; 984 1048 } 985 1049 986 1050 bool ScriptInterface::LoadGlobalScript(const VfsPath& filename, const std::wstring& code) 987 1051 { 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 1052 JSAutoRequest rq(m->m_cx); 1053 utf16string codeUtf16(code.begin(), code.end()); 1054 uint lineNo = 1; 993 1055 994 1056 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()),1057 bool ok = JS_EvaluateUCScript(m->m_cx, m->m_glob, 1058 reinterpret_cast<const jschar*> (codeUtf16.c_str()), (uint)(codeUtf16.length()), 997 1059 utf8_from_wstring(filename.string()).c_str(), lineNo, &rval); 998 1060 999 return ok ? true : false;1061 return ok; 1000 1062 } 1001 1063 1002 1064 bool ScriptInterface::LoadGlobalScriptFile(const VfsPath& path) 1003 1065 { 1066 JSAutoRequest rq(m->m_cx); 1004 1067 if (!VfsFileExists(path)) 1005 1068 { 1006 1069 LOGERROR(L"File '%ls' does not exist", path.string().c_str()); … … 1019 1082 1020 1083 std::wstring code = wstring_from_utf8(file.DecodeUTF8()); // assume it's UTF-8 1021 1084 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 1085 utf16string codeUtf16(code.begin(), code.end()); 1086 uint lineNo = 1; 1027 1087 1028 1088 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()),1089 bool ok = JS_EvaluateUCScript(m->m_cx, m->m_glob, 1090 reinterpret_cast<const jschar*> (codeUtf16.c_str()), (uint)(codeUtf16.length()), 1031 1091 utf8_from_wstring(path.string()).c_str(), lineNo, &rval); 1032 1092 1033 return ok ? true : false;1093 return ok; 1034 1094 } 1035 1095 1036 1096 … … 1042 1102 1043 1103 bool ScriptInterface::Eval_(const char* code, jsval& rval) 1044 1104 { 1105 JSAutoRequest rq(m->m_cx); 1045 1106 utf16string codeUtf16(code, code+strlen(code)); 1046 1107 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;1108 bool ok = JS_EvaluateUCScript(m->m_cx, m->m_glob, (const jschar*)codeUtf16.c_str(), (uint)codeUtf16.length(), "(eval)", 1, &rval); 1109 return ok; 1049 1110 } 1050 1111 1051 1112 bool ScriptInterface::Eval_(const wchar_t* code, jsval& rval) 1052 1113 { 1114 JSAutoRequest rq(m->m_cx); 1053 1115 utf16string codeUtf16(code, code+wcslen(code)); 1054 1116 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;1117 bool ok = JS_EvaluateUCScript(m->m_cx, m->m_glob, (const jschar*)codeUtf16.c_str(), (uint)codeUtf16.length(), "(eval)", 1, &rval); 1118 return ok; 1057 1119 } 1058 1120 1059 1121 CScriptValRooted ScriptInterface::ParseJSON(const std::string& string_utf8) 1060 1122 { 1123 JSAutoRequest rq(m->m_cx); 1061 1124 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 1125 utf16string string(attrsW.begin(), attrsW.end()); 1126 JS::Rooted<jsval> vp(m->m_cx); 1127 JS_ParseJSON(m->m_cx, reinterpret_cast<const jschar*>(string.c_str()), (uint32_t)string.size(), &vp); 1084 1128 return CScriptValRooted(m->m_cx, vp); 1085 1129 } 1086 1130 … … 1109 1153 1110 1154 struct Stringifier 1111 1155 { 1112 static JSBool callback(const jschar* buf, uint32len, void* data)1156 static bool callback(const jschar* buf, uint32_t len, void* data) 1113 1157 { 1114 1158 utf16string str(buf, buf+len); 1115 1159 std::wstring strw(str.begin(), str.end()); 1116 1160 1117 1161 Status err; // ignore Unicode errors 1118 1162 static_cast<Stringifier*>(data)->stream << utf8_from_wstring(strw, &err); 1119 return JS_TRUE;1163 return true; 1120 1164 } 1121 1165 1122 1166 std::stringstream stream; … … 1124 1168 1125 1169 struct StringifierW 1126 1170 { 1127 static JSBool callback(const jschar* buf, uint32len, void* data)1171 static bool callback(const jschar* buf, uint32_t len, void* data) 1128 1172 { 1129 1173 utf16string str(buf, buf+len); 1130 1174 static_cast<StringifierW*>(data)->stream << std::wstring(str.begin(), str.end()); 1131 return JS_TRUE;1175 return true; 1132 1176 } 1133 1177 1134 1178 std::wstringstream stream; … … 1136 1180 1137 1181 std::string ScriptInterface::StringifyJSON(jsval obj, bool indent) 1138 1182 { 1183 JSAutoRequest rq(m->m_cx); 1139 1184 Stringifier str; 1140 1185 if (!JS_Stringify(m->m_cx, &obj, NULL, indent ? INT_TO_JSVAL(2) : JSVAL_VOID, &Stringifier::callback, &str)) 1141 1186 { … … 1151 1196 1152 1197 std::wstring ScriptInterface::ToString(jsval obj, bool pretty) 1153 1198 { 1199 JSAutoRequest rq(m->m_cx); 1154 1200 if (JSVAL_IS_VOID(obj)) 1155 1201 return L"(void 0)"; 1156 1202 … … 1163 1209 // Temporary disable the error reporter, so we don't print complaints about cyclic values 1164 1210 JSErrorReporter er = JS_SetErrorReporter(m->m_cx, NULL); 1165 1211 1166 bool ok = JS_Stringify(m->m_cx, &obj, NULL, INT_TO_JSVAL(2), &StringifierW::callback, &str) == JS_TRUE;1212 bool ok = JS_Stringify(m->m_cx, &obj, NULL, INT_TO_JSVAL(2), &StringifierW::callback, &str) == true; 1167 1213 1168 1214 // Restore error reporter 1169 1215 JS_SetErrorReporter(m->m_cx, er); … … 1185 1231 1186 1232 void ScriptInterface::ReportError(const char* msg) 1187 1233 { 1234 JSAutoRequest rq(m->m_cx); 1188 1235 // JS_ReportError by itself doesn't seem to set a JS-style exception, and so 1189 1236 // script callers will be unable to catch anything. So use JS_SetPendingException 1190 1237 // to make sure there really is a script-level exception. But just set it to undefined … … 1198 1245 1199 1246 bool ScriptInterface::IsExceptionPending(JSContext* cx) 1200 1247 { 1248 JSAutoRequest rq(cx); 1201 1249 return JS_IsExceptionPending(cx) ? true : false; 1202 1250 } 1203 1251 1204 JSClass* ScriptInterface::GetClass(JS Context* cx, JSObject* obj)1252 JSClass* ScriptInterface::GetClass(JSObject* obj) 1205 1253 { 1206 UNUSED2(cx); // unused if not JS_THREADSAFE 1207 1208 return JS_GET_CLASS(cx, obj); 1254 return JS_GetClass(obj); 1209 1255 } 1210 1256 1211 void* ScriptInterface::GetPrivate(JS Context* cx, JSObject* obj)1257 void* ScriptInterface::GetPrivate(JSObject* obj) 1212 1258 { 1213 1259 // TODO: use JS_GetInstancePrivate 1214 return JS_GetPrivate( cx,obj);1260 return JS_GetPrivate(obj); 1215 1261 } 1216 1262 1217 1263 void ScriptInterface::DumpHeap() 1218 1264 { 1219 1265 #if MOZJS_DEBUG_ABI 1220 JS_DumpHeap( m->m_cx, stderr, NULL, 0, NULL, (size_t)-1, NULL);1266 JS_DumpHeap(GetJSRuntime(), stderr, NULL, JSTRACE_OBJECT, NULL, (size_t)-1, NULL); 1221 1267 #endif 1222 1268 fprintf(stderr, "# Bytes allocated: %u\n", JS_GetGCParameter(GetJSRuntime(), JSGC_BYTES)); 1223 JS_GC( m->m_cx);1269 JS_GC(GetJSRuntime()); 1224 1270 fprintf(stderr, "# Bytes allocated after GC: %u\n", JS_GetGCParameter(GetJSRuntime(), JSGC_BYTES)); 1225 1271 } 1226 1272 … … 1259 1305 // Clone a new value (and root it and add it to the mapping) 1260 1306 jsval Clone(jsval val) 1261 1307 { 1308 JSAutoRequest rq(cxFrom); 1262 1309 if (JSVAL_IS_DOUBLE(val)) 1263 1310 { 1264 jsval rval ;1265 CLONE_REQUIRE( JS_NewNumberValue(cxTo, JSVAL_TO_DOUBLE(val), &rval), L"JS_NewNumberValue");1311 jsval rval = JS_NumberValue(JSVAL_TO_DOUBLE(val)); 1312 CLONE_REQUIRE(!JSVAL_IS_VOID(rval), L"JS_NumberValue"); 1266 1313 m_RooterTo.Push(rval); 1267 1314 return rval; 1268 1315 } … … 1272 1319 size_t len; 1273 1320 const jschar* chars = JS_GetStringCharsAndLength(cxFrom, JSVAL_TO_STRING(val), &len); 1274 1321 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; 1322 { 1323 JSAutoRequest rq(cxTo); 1324 JSString* str = JS_NewUCStringCopyN(cxTo, chars, len); 1325 CLONE_REQUIRE(str, L"JS_NewUCStringCopyN"); 1326 jsval rval = STRING_TO_JSVAL(str); 1327 m_Mapping[JSVAL_TO_GCTHING(val)] = rval; 1328 m_RooterTo.Push(rval); 1329 return rval; 1330 } 1281 1331 } 1282 1332 1283 ENSURE( JSVAL_IS_OBJECT(val));1333 ENSURE(!JSVAL_IS_PRIMITIVE(val)); 1284 1334 1285 1335 JSObject* newObj; 1286 1336 if (JS_IsArrayObject(cxFrom, JSVAL_TO_OBJECT(val))) 1287 1337 { 1288 jsuint length;1338 uint length; 1289 1339 CLONE_REQUIRE(JS_GetArrayLength(cxFrom, JSVAL_TO_OBJECT(val), &length), L"JS_GetArrayLength"); 1290 newObj = JS_NewArrayObject(cxTo, length, NULL); 1340 { 1341 JSAutoRequest rq(cxTo); 1342 newObj = JS_NewArrayObject(cxTo, length, NULL); 1343 } 1291 1344 CLONE_REQUIRE(newObj, L"JS_NewArrayObject"); 1292 1345 } 1293 1346 else 1294 1347 { 1295 newObj = JS_NewObject(cxTo, NULL, NULL, NULL); 1348 { 1349 JSAutoRequest rq(cxTo); 1350 newObj = JS_NewObject(cxTo, NULL, NULL, NULL); 1351 } 1296 1352 CLONE_REQUIRE(newObj, L"JS_NewObject"); 1297 1353 } 1298 1354 1299 1355 m_Mapping[JSVAL_TO_GCTHING(val)] = OBJECT_TO_JSVAL(newObj); 1300 1356 m_RooterTo.Push(newObj); 1301 1357 1302 AutoJSIdArray ida (cxFrom, JS_Enumerate(cxFrom, JSVAL_TO_OBJECT(val))); 1303 CLONE_REQUIRE(ida.get(), L"JS_Enumerate"); 1358 JS::AutoIdArray ida (cxFrom, JS_Enumerate(cxFrom, JSVAL_TO_OBJECT(val))); 1359 CLONE_REQUIRE(ida, L"JS_Enumerate"); 1360 1361 // AutoGCRooter idaRooter(scriptInterfaceFrom); 1362 // idaRooter.Push(&ida); 1304 1363 1305 AutoGCRooter idaRooter(scriptInterfaceFrom);1306 idaRooter.Push(ida.get());1307 1308 1364 for (size_t i = 0; i < ida.length(); ++i) 1309 1365 { 1310 1366 jsid id = ida[i]; 1311 jsval idval, propval; 1312 CLONE_REQUIRE(JS_IdToValue(cxFrom, id, &idval), L"JS_IdToValue"); 1367 JS::RootedValue idval(cxTo); 1368 JS::RootedValue propval(cxTo); 1369 CLONE_REQUIRE(JS_IdToValue(cxFrom, id, idval.address()), L"JS_IdToValue"); 1313 1370 CLONE_REQUIRE(JS_GetPropertyById(cxFrom, JSVAL_TO_OBJECT(val), id, &propval), L"JS_GetPropertyById"); 1314 jsval newPropval = GetOrClone(propval);1371 JS::RootedValue newPropval(cxTo, GetOrClone(propval)); 1315 1372 1316 1373 if (JSVAL_IS_INT(idval)) 1317 1374 { 1318 1375 // int jsids are portable across runtimes 1319 CLONE_REQUIRE(JS_SetPropertyById(cxTo, newObj, id, &newPropval), L"JS_SetPropertyById"); 1320 } 1376 JSAutoRequest rq(cxTo); 1377 CLONE_REQUIRE(JS_SetPropertyById(cxTo, newObj, id, newPropval), L"JS_SetPropertyById"); 1378 } 1321 1379 else if (JSVAL_IS_STRING(idval)) 1322 1380 { 1323 1381 // string jsids are runtime-specific, so we need to copy the string content … … 1326 1384 size_t len; 1327 1385 const jschar* chars = JS_GetStringCharsAndLength(cxFrom, idstr, &len); 1328 1386 CLONE_REQUIRE(idstr, L"JS_GetStringCharsAndLength (id)"); 1329 CLONE_REQUIRE(JS_SetUCProperty(cxTo, newObj, chars, len, &newPropval), L"JS_SetUCProperty"); 1387 { 1388 JSAutoRequest rq(cxTo); 1389 CLONE_REQUIRE(JS_SetUCProperty(cxTo, newObj, chars, len, newPropval), L"JS_SetUCProperty"); 1390 } 1330 1391 } 1331 1392 else 1332 1393 { … … 1354 1415 } 1355 1416 1356 1417 ScriptInterface::StructuredClone::StructuredClone() : 1357 m_ Context(NULL), m_Data(NULL), m_Size(0)1418 m_Data(NULL), m_Size(0) 1358 1419 { 1359 1420 } 1360 1421 1361 1422 ScriptInterface::StructuredClone::~StructuredClone() 1362 1423 { 1363 1424 if (m_Data) 1364 JS_ free(m_Context, m_Data);1425 JS_ClearStructuredClone(m_Data, m_Size); 1365 1426 } 1366 1427 1367 1428 shared_ptr<ScriptInterface::StructuredClone> ScriptInterface::WriteStructuredClone(jsval v) 1368 1429 { 1369 uint64* data = NULL; 1430 JSAutoRequest rq(m->m_cx); 1431 uint64_t* data = NULL; 1370 1432 size_t nbytes = 0; 1371 if (!JS_WriteStructuredClone(m->m_cx, v, &data, &nbytes, NULL, NULL ))1433 if (!JS_WriteStructuredClone(m->m_cx, v, &data, &nbytes, NULL, NULL, JSVAL_VOID)) 1372 1434 { 1373 1435 debug_warn(L"Writing a structured clone with JS_WriteStructuredClone failed!"); 1374 1436 return shared_ptr<StructuredClone>(); 1375 1437 } 1376 1438 1377 1439 shared_ptr<StructuredClone> ret (new StructuredClone); 1378 ret->m_Context = m->m_cx;1379 1440 ret->m_Data = data; 1380 1441 ret->m_Size = nbytes; 1381 1442 return ret; … … 1383 1444 1384 1445 jsval ScriptInterface::ReadStructuredClone(const shared_ptr<ScriptInterface::StructuredClone>& ptr) 1385 1446 { 1447 JSAutoRequest rq(m->m_cx); 1386 1448 jsval ret = JSVAL_VOID; 1387 1449 JS_ReadStructuredClone(m->m_cx, ptr->m_Data, ptr->m_Size, JS_STRUCTURED_CLONE_VERSION, &ret, NULL, NULL); 1388 1450 return ret; -
source/scriptinterface/AutoRooters.h
20 20 21 21 #include "scriptinterface/ScriptTypes.h" 22 22 23 #include "js /jsapi.h"23 #include "jsapi.h" 24 24 25 25 /** 26 26 * Helper for rooting large groups of script values. -
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