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