Ticket #1886: SpiderMonkeyESR24_v0.9.diff

File SpiderMonkeyESR24_v0.9.diff, 174.9 KB (added by Yves, 10 years ago)

Current WIP patch for ESR24. This version is with incremental GC. It's still WIP and there are still some known errors.

  • 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
     
    562562    },
    563563    spidermonkey = {
    564564        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" }
    570571            else
    571572                if os.is("windows") then
    572573                    include_dir = "include-win32"
    573574                elseif os.is("macosx") then
    574                     include_dir = "include"
     575                    include_dir = "include-unix"
    575576                else
    576577                    include_dir = "include-unix"
    577578                end
    578579                configuration "Debug"
    579                     includedirs { libraries_source_dir.."spidermonkey/"..include_dir }
     580                    includedirs { libraries_source_dir.."spidermonkey/"..include_dir.."-debug" }
     581                    defines { "DEBUG" }
    580582                configuration "Release"
    581                     includedirs { libraries_source_dir.."spidermonkey/"..include_dir }
     583                    includedirs { libraries_source_dir.."spidermonkey/"..include_dir.."-release" }
    582584                configuration { }
    583585            end
    584586        end,
    585587        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
    592595            else
    593596                configuration "Debug"
    594                     links { "mozjs185-ps-debug" }
     597                    links { "mozjs24-ps-debug" }
    595598                configuration "Release"
    596                     links { "mozjs185-ps-release" }
     599                    links { "mozjs24-ps-release" }
    597600                configuration { }
    598601                add_source_lib_paths("spidermonkey")
    599602            end
  • build/premake/premake4.lua

     
    1515newoption { trigger = "with-system-nvtt", description = "Search standard paths for nvidia-texture-tools library, instead of using bundled copy" }
    1616newoption { trigger = "with-system-enet", description = "Search standard paths for libenet, instead of using bundled copy" }
    1717newoption { trigger = "with-system-miniupnpc", description = "Search standard paths for libminiupnpc, instead of using bundled copy" }
    18 newoption { trigger = "with-system-mozjs185", description = "Search standard paths for libmozjs185, instead of using bundled copy" }
     18newoption { trigger = "with-system-mozjs24", description = "Search standard paths for libmozjs24, instead of using bundled copy" }
    1919newoption { trigger = "with-c++11", description = "Enable C++11 on GCC" }
    2020newoption { trigger = "sysroot", description = "Set compiler system root path, used for building against a non-system SDK. For example /usr/local becomes SYSROOT/user/local" }
    2121newoption { 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

     
    55then run start-msvc8.bat and run ./build.sh here.
    66
    77This 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)
     8https://ftp.mozilla.org/pub/mozilla.org/js/mozjs-24.2.0.tar.bz2
    109
    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.
     10The game must be compiled with precisely this version since SpiderMonkey
     11does not guarantee API stability and may have behavioural changes that
     12cause subtle bugs or network out-of-sync errors.
     13A standard system-provided version of the library may only be used if it's
     14exactly the same version or if it's another minor release that does not
     15change the behaviour of the scripts executed by SpiderMonkey.
  • libraries/source/spidermonkey/build.sh

     
    1717echo "Building SpiderMonkey..."
    1818echo
    1919
    20 JOBS=${JOBS:="-j2"}
     20
     21JOBS=${JOBS:="-j5"}
    2122MAKE=${MAKE:="make"}
    2223
    2324MAKE_OPTS="${JOBS}"
     25NSPR_INCLUDES="`pkg-config nspr --cflags`"
     26NSPR_LIBS="`pkg-config nspr --libs`"
    2427
    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)
     28CONF_OPTS="--disable-e4x --enable-threadsafe --enable-shared-js --disable-tests" # --enable-trace-logging"
    2829
    2930# If Valgrind looks like it's installed, then set up SM to support it
    3031# (else the JITs will interact poorly with it)
     
    3334  CONF_OPTS="${CONF_OPTS} --enable-valgrind"
    3435fi
    3536
    36 #CONF_OPTS="${CONF_OPTS} --enable-threadsafe --with-system-nspr"
    37 #CONF_OPTS="${CONF_OPTS} --enable-trace-jscalls"
    38 
    3937# We need to be able to override CHOST in case it is 32bit userland on 64bit kernel
    4038CONF_OPTS="${CONF_OPTS} \
    4139  ${CBUILD:+--build=${CBUILD}} \
     
    4341  ${CTARGET:+--target=${CTARGET}}"
    4442
    4543echo "SpiderMonkey build options: ${CONF_OPTS}"
     44echo ${CONF_OPTS}
    4645
    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
     47rm -rf mozjs24
     48tar xjf mozjs-24.2.0.tar.bz2
    4949
    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
    5352
    54 cd js-1.8.5/js/src
     53# rename the extracted directory to something shorter
     54mv mozjs-24.2.0 mozjs24
    5555
     56cd mozjs24/js/src
     57
    5658# We want separate debug/release versions of the library, so we have to change
    5759# the LIBRARY_NAME for each build.
    5860# (We use perl instead of sed so that it works with MozillaBuild on Windows,
    5961# which has an ancient sed.)
    60 perl -i.bak -pe 's/^(LIBRARY_NAME\s+= mozjs185)(-ps-debug|-ps-release)?/$1-ps-debug/' Makefile.in
     62perl -i.bak -pe 's/(^LIBRARY_NAME\s+=).*/$1mozjs24-ps-debug/' Makefile.in
    6163mkdir -p build-debug
    6264cd build-debug
    63 ../configure ${CONF_OPTS} --enable-debug --disable-optimize
     65../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
    6466${MAKE} ${MAKE_OPTS}
    6567cd ..
    6668
    67 perl -i.bak -pe 's/^(LIBRARY_NAME\s+= mozjs185)(-ps-debug|-ps-release)?/$1-ps-release/' Makefile.in
     69perl -i.bak -pe 's/(^LIBRARY_NAME\s+=).*/$1mozjs24-ps-release/' Makefile.in
    6870mkdir -p build-release
    6971cd build-release
    70 ../configure ${CONF_OPTS} # --enable-gczeal --enable-debug-symbols
     72../configure ${CONF_OPTS} --with-nspr-libs="$NSPR_LIBS" --with-nspr-cflags="$NSPR_INCLUDES" --enable-optimize  # --enable-gczeal --enable-debug-symbols
    7173${MAKE} ${MAKE_OPTS}
    7274cd ..
    7375
    74 # Remove the library suffixes to avoid spurious SVN diffs
    75 perl -i.bak -pe 's/^(LIBRARY_NAME\s+= mozjs185)(-ps-debug|-ps-release)?/$1/' Makefile.in
    76 
    7776cd ../../..
    7877
    7978if [ "${OS}" = "Windows_NT" ]
    8079then
    81   INCLUDE_DIR=include-win32
     80  INCLUDE_DIR_DEBUG=include-win32-debug
     81  INCLUDE_DIR_RELEASE=include-win32-release
    8282  DLL_SRC_SUFFIX=-1.0.dll
    8383  DLL_DST_SUFFIX=-1.0.dll
    8484  LIB_PREFIX=
    8585  LIB_SRC_SUFFIX=-1.0.lib
    8686  LIB_DST_SUFFIX=.lib
    8787else
    88   INCLUDE_DIR=include-unix
     88  INCLUDE_DIR_DEBUG=include-unix-debug
     89  INCLUDE_DIR_RELEASE=include-unix-release
    8990  DLL_SRC_SUFFIX=.so
    90   DLL_DST_SUFFIX=.so.1.0
     91  DLL_DST_SUFFIX=.so
    9192  LIB_PREFIX=lib
    9293  LIB_SRC_SUFFIX=.so
    9394  LIB_DST_SUFFIX=.so
     
    102103
    103104# Copy files into the necessary locations for building and running the game
    104105
    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
     107mkdir -p ${INCLUDE_DIR_DEBUG}
     108mkdir -p ${INCLUDE_DIR_RELEASE}
     109cp -R -L mozjs24/js/src/build-release/dist/include/* ${INCLUDE_DIR_RELEASE}/
     110cp -R -L mozjs24/js/src/build-debug/dist/include/* ${INCLUDE_DIR_DEBUG}/
    108111
    109112mkdir -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}
     113cp -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}
     114cp -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}
     115cp -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}
     116cp -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}
    114117
    115118# Flag that it's already been built successfully so we can skip it next time
    116119touch .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.cpp
    2 +++ js-1.8.5/js/src/jsnativestack.cpp
    3 @@ -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  # endif
    11  
    12 @@ -196,7 +196,9 @@
    13  # else
    14      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  #  else
    23 @@ -212,7 +214,13 @@
    24  #  ifdef DEBUG
    25      int rc =
    26  #  endif
    27 +# 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 +# else
    32          pthread_attr_getstack(&sattr, &stackBase, &stackSize);
    33 +# endif
    34      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.in
    2 +++ js-1.8.5/js/src/configure.in
    3 @@ -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/configure
    14 +++ js-1.8.5/js/src/configure
    15 @@ -8093,6 +8093,12 @@
    16  EOF
    17  
    18      ;;
    19 +*-openbsd*)
    20 +    cat >> confdefs.h <<\EOF
    21 +#define AVMPLUS_UNIX 1
    22 +EOF
    23 +
    24 +    ;;
    25  *-gnu*)
    26      cat >> confdefs.h <<\EOF
    27  #define AVMPLUS_UNIX 1
  • source/gui/IGUIObject.cpp

     
    420420        throw PSERROR_GUI_OperationNeedsGUIObject();
    421421       
    422422    JSContext* cx = pGUI->GetScriptInterface()->GetContext();
     423    JSAutoRequest rq(cx);
    423424   
    424425    const int paramCount = 1;
    425426    const char* paramNames[paramCount] = { "mouse" };
     
    467468        return;
    468469
    469470    JSContext* cx = m_pGUI->GetScriptInterface()->GetContext();
    470 
     471    JSAutoRequest rq(cx);
     472   
    471473    // Set up the 'mouse' parameter
    472474    CScriptVal mouse;
    473475    m_pGUI->GetScriptInterface()->Eval("({})", mouse);
     
    478480    jsval paramData[] = { mouse.get() };
    479481
    480482    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);
    482484    if (!ok)
    483485    {
    484486        // We have no way to propagate the script exception, so just ignore it
     
    498500    jsval arg = Argument.get();
    499501
    500502    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);
    502504    if (!ok)
    503505    {
    504506        JS_ReportError(cx, "Errors executing script action \"%s\"", Action.c_str());
     
    508510JSObject* IGUIObject::GetJSObject()
    509511{
    510512    JSContext* cx = m_pGUI->GetScriptInterface()->GetContext();
     513    JSAutoRequest rq(cx);
    511514    // Cache the object when somebody first asks for it, because otherwise
    512515    // we end up doing far too much object allocation. TODO: Would be nice to
    513516    // not have these objects hang around forever using up memory, though.
     
    515518    {
    516519        JSObject* obj = JS_NewObject(cx, &JSI_IGUIObject::JSI_class, NULL, NULL);
    517520        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);
    519522    }
    520523    return JSVAL_TO_OBJECT(m_JSObject.get());;
    521524}
  • source/gui/IGUIObject.h

     
    142142    friend class GUITooltip;
    143143
    144144    // Allow getProperty to access things like GetParent()
    145     friend JSBool JSI_IGUIObject::getProperty(JSContext* cx, JSObject* obj, jsid id, jsval* vp);
    146     friend JSBool JSI_IGUIObject::setProperty(JSContext* cx, JSObject* obj, jsid id, JSBool strict, jsval* vp);
    147     friend JSBool JSI_IGUIObject::getComputedSize(JSContext* cx, uintN argc, 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);
    148148
    149149public:
    150150    IGUIObject();
  • source/gui/scripting/GuiScriptConversions.cpp

     
    2323#include "lib/external_libraries/libsdl.h"
    2424#include "ps/Hotkey.h"
    2525
    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()))
    2927    // ignore JS_SetProperty return value, because errors should be impossible
    3028    // and we can't do anything useful in the case of errors anyway
    3129
    3230template<> jsval ScriptInterface::ToJSVal<SDL_Event_>(JSContext* cx, SDL_Event_ const& val)
    3331{
     32    JSAutoRequest rq(cx);
    3433    const char* typeName;
    3534
    3635    switch (val.ev.type)
     
    7877        JSObject* keysym = JS_NewObject(cx, NULL, NULL, NULL);
    7978        if (! keysym)
    8079            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());
    8382
    8483        // SET(keysym, "scancode", (int)val.ev.key.keysym.scancode); // (not in wsdl.h)
    8584        SET(keysym, "sym", (int)val.ev.key.keysym.sym);
  • source/gui/scripting/JSInterface_GUITypes.cpp

     
    2323/**** GUISize ****/
    2424JSClass JSI_GUISize::JSI_class = {
    2525    "GUISize", 0,
    26         JS_PropertyStub, JS_PropertyStub,
     26        JS_PropertyStub, JS_DeletePropertyStub,
    2727        JS_PropertyStub, JS_StrictPropertyStub,
    2828        JS_EnumerateStub, JS_ResolveStub,
    29         JS_ConvertStub, JS_FinalizeStub,
     29        JS_ConvertStub, NULL,
    3030        NULL, NULL, NULL, JSI_GUISize::construct
    3131};
    3232
     
    4545
    4646JSFunctionSpec JSI_GUISize::JSI_methods[] =
    4747{
    48     { "toString", JSI_GUISize::toString, 0, 0 },
    49     { 0 }
     48    JS_FS("toString", JSI_GUISize::toString, 0, 0),
     49    JS_FS_END
    5050};
    5151
    52 JSBool JSI_GUISize::construct(JSContext* cx, uintN argc, jsval* vp)
     52JSBool JSI_GUISize::construct(JSContext* cx, uint argc, jsval* vp)
    5353{
    5454    JSObject* obj = JS_NewObject(cx, &JSI_GUISize::JSI_class, NULL, NULL);
    5555
     56    // TODO: ugly with so much repetition...?
    5657    if (argc == 8)
    5758    {
    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());
    6675    }
    6776    else if (argc == 4)
    6877    {
    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());
    7891    }
    7992    else
    8093    {
    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());
    90103    }
    91104
    92105    JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(obj));
     
    102115        return CStr::FromDouble(per)+"%"+( pix == 0.0 ? CStr() : pix > 0.0 ? CStr("+")+CStr::FromDouble(pix) : CStr::FromDouble(pix) );
    103116}
    104117
    105 JSBool JSI_GUISize::toString(JSContext* cx, uintN argc, jsval* vp)
     118JSBool JSI_GUISize::toString(JSContext* cx, uint argc, jsval* vp)
    106119{
    107120    UNUSED2(argc);
    108121
     
    141154
    142155JSClass JSI_GUIColor::JSI_class = {
    143156    "GUIColor", 0,
    144         JS_PropertyStub, JS_PropertyStub,
     157        JS_PropertyStub, JS_DeletePropertyStub,
    145158        JS_PropertyStub, JS_StrictPropertyStub,
    146159        JS_EnumerateStub, JS_ResolveStub,
    147         JS_ConvertStub, JS_FinalizeStub,
     160        JS_ConvertStub, NULL,
    148161        NULL, NULL, NULL, JSI_GUIColor::construct
    149162};
    150163
     
    159172
    160173JSFunctionSpec JSI_GUIColor::JSI_methods[] =
    161174{
    162     { "toString", JSI_GUIColor::toString, 0, 0 },
    163     { 0 }
     175    JS_FS("toString", JSI_GUIColor::toString, 0, 0),
     176    JS_FS_END
    164177};
    165178
    166 JSBool JSI_GUIColor::construct(JSContext* cx, uintN argc, jsval* vp)
     179JSBool JSI_GUIColor::construct(JSContext* cx, uint argc, jsval* vp)
    167180{
    168181    JSObject* obj = JS_NewObject(cx, &JSI_GUIColor::JSI_class, NULL, NULL);
    169182
     
    177190    else
    178191    {
    179192        // 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))
    182195            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))
    187201            return JS_FALSE;
    188         JS_SetProperty(cx, obj, "g", &c);
     202        JS_SetProperty(cx, obj, "g", c.address());
    189203    }
    190204
    191205    JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(obj));
    192206    return JS_TRUE;
    193207}
    194208
    195 JSBool JSI_GUIColor::toString(JSContext* cx, uintN argc, jsval* vp)
     209JSBool JSI_GUIColor::toString(JSContext* cx, uint argc, jsval* vp)
    196210{
    197211    UNUSED2(argc);
    198212
     
    218232
    219233JSClass JSI_GUIMouse::JSI_class = {
    220234    "GUIMouse", 0,
    221         JS_PropertyStub, JS_PropertyStub,
     235        JS_PropertyStub, JS_DeletePropertyStub,
    222236        JS_PropertyStub, JS_StrictPropertyStub,
    223237        JS_EnumerateStub, JS_ResolveStub,
    224         JS_ConvertStub, JS_FinalizeStub,
     238        JS_ConvertStub, NULL,
    225239        NULL, NULL, NULL, JSI_GUIMouse::construct
    226240};
    227241
     
    235249
    236250JSFunctionSpec JSI_GUIMouse::JSI_methods[] =
    237251{
    238     { "toString", JSI_GUIMouse::toString, 0, 0 },
    239     { 0 }
     252    JS_FS("toString", JSI_GUIMouse::toString, 0, 0),
     253    JS_FS_END
    240254};
    241255
    242 JSBool JSI_GUIMouse::construct(JSContext* cx, uintN argc, jsval* vp)
     256JSBool JSI_GUIMouse::construct(JSContext* cx, uint argc, jsval* vp)
    243257{
    244258    JSObject* obj = JS_NewObject(cx, &JSI_GUIMouse::JSI_class, NULL, NULL);
    245259
    246260    if (argc == 3)
    247261    {
    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());
    251268    }
    252269    else
    253270    {
    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());
    258275    }
    259276
    260277    JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(obj));
    261278    return JS_TRUE;
    262279}
    263280
    264 JSBool JSI_GUIMouse::toString(JSContext* cx, uintN argc, jsval* vp)
     281JSBool JSI_GUIMouse::toString(JSContext* cx, uint argc, jsval* vp)
    265282{
    266283    UNUSED2(argc);
    267284
    268     int32 x, y, buttons;
     285    int32_t x, y, buttons;
    269286    ScriptInterface* pScriptInterface = ScriptInterface::GetScriptInterfaceAndCBData(cx)->pScriptInterface;
    270287    pScriptInterface->GetProperty(JS_THIS_VALUE(cx, vp), "x", x);
    271288    pScriptInterface->GetProperty(JS_THIS_VALUE(cx, vp), "y", y);
  • source/gui/scripting/JSInterface_GUITypes.h

     
    2626        extern JSClass JSI_class;               \
    2727        extern JSPropertySpec JSI_props[];      \
    2828        extern JSFunctionSpec JSI_methods[];    \
    29         JSBool construct(JSContext* cx, uintN argc, jsval* vp); \
    30         JSBool toString(JSContext* cx, uintN argc, jsval* vp);  \
     29        JSBool construct(JSContext* cx, uint argc, jsval* vp);  \
     30        JSBool toString(JSContext* cx, uint argc, jsval* vp);   \
    3131    }
    3232
    3333GUISTDTYPE(Size)
  • source/gui/scripting/JSInterface_IGUIObject.cpp

     
    3232
    3333JSClass JSI_IGUIObject::JSI_class = {
    3434    "GUIObject", JSCLASS_HAS_PRIVATE,
    35     JS_PropertyStub, JS_PropertyStub,
     35    JS_PropertyStub, JS_DeletePropertyStub,
    3636    JSI_IGUIObject::getProperty, JSI_IGUIObject::setProperty,
    3737    JS_EnumerateStub, JS_ResolveStub,
    38     JS_ConvertStub, JS_FinalizeStub,
     38    JS_ConvertStub, NULL,
    3939    NULL, NULL, NULL, JSI_IGUIObject::construct
    4040};
    4141
    42 JSPropertySpec JSI_IGUIObject::JSI_props[] = 
     42JSPropertySpec JSI_IGUIObject::JSI_props[] =
    4343{
    4444    { 0 }
    4545};
    4646
    47 JSFunctionSpec JSI_IGUIObject::JSI_methods[] = 
     47JSFunctionSpec JSI_IGUIObject::JSI_methods[] =
    4848{
    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
    5454};
    5555
    56 JSBool JSI_IGUIObject::getProperty(JSContext* cx, JSObject* obj, jsid id, jsval* vp)
     56JSBool JSI_IGUIObject::getProperty(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JS::MutableHandle<jsval> vp)
    5757{
    5858    IGUIObject* e = (IGUIObject*)JS_GetInstancePrivate(cx, obj, &JSI_IGUIObject::JSI_class, NULL);
    5959    if (!e)
     
    8888        CStr eventName (CStr(propName.substr(2)).LowerCase());
    8989        std::map<CStr, CScriptValRooted>::iterator it = e->m_ScriptHandlers.find(eventName);
    9090        if (it == e->m_ScriptHandlers.end())
    91             *vp = JSVAL_NULL;
     91            vp.set(JSVAL_NULL);
    9292        else
    93             *vp = it->second.get();
     93            vp.set((*it).second.get());
    9494        return JS_TRUE;
    9595    }
    9696
     
    102102        if (parent)
    103103        {
    104104            // 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()));
    106106        }
    107107        else
    108108        {
    109109            // Return null if there's no parent
    110             *vp = JSVAL_NULL;
     110            vp.set(JSVAL_NULL);
    111111        }
    112112        return JS_TRUE;
    113113    }
    114114    // Also handle "name" specially
    115115    else if (propName == "name")
    116116    {
    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())));
    118118        return JS_TRUE;
    119119    }
    120120    // Handle all other properties
     
    135135            {
    136136                bool value;
    137137                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;
    139140                break;
    140141            }
    141142
     
    143144            {
    144145                int value;
    145146                GUI<int>::GetSetting(e, propName, value);
    146                 *vp = INT_TO_JSVAL(value);
     147                vp.set(INT_TO_JSVAL(value));
    147148                break;
    148149            }
    149150
     
    152153                float value;
    153154                GUI<float>::GetSetting(e, propName, value);
    154155                // 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());
    156158            }
    157159
    158160        case GUIST_CColor:
     
    160162                CColor colour;
    161163                GUI<CColor>::GetSetting(e, propName, colour);
    162164                JSObject* obj = JS_NewObject(cx, &JSI_GUIColor::JSI_class, NULL, NULL);
    163                 *vp = OBJECT_TO_JSVAL(obj); // root it
     165                vp.set(OBJECT_TO_JSVAL(obj)); // root it
    164166
    165                 jsval c;
     167                JS::RootedValue c(cx);
    166168                // 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())
    168171                    P(r);
    169172                    P(g);
    170173                    P(b);
     
    179182                CClientArea area;
    180183                GUI<CClientArea>::GetSetting(e, propName, area);
    181184                JSObject* obj = JS_NewObject(cx, &JSI_GUISize::JSI_class, NULL, NULL);
    182                 *vp = OBJECT_TO_JSVAL(obj); // root it
     185                vp.set(OBJECT_TO_JSVAL(obj)); // root it
    183186                try
    184187                {
    185188                    ScriptInterface* pScriptInterface = ScriptInterface::GetScriptInterfaceAndCBData(cx)->pScriptInterface;
     
    207210            {
    208211                CGUIString value;
    209212                GUI<CGUIString>::GetSetting(e, propName, value);
    210                 *vp = ScriptInterface::ToJSVal(cx, value.GetOriginalString());
     213                vp.set(ScriptInterface::ToJSVal(cx, value.GetOriginalString()));
    211214                break;
    212215            }
    213216
     
    215218            {
    216219                CStr value;
    217220                GUI<CStr>::GetSetting(e, propName, value);
    218                 *vp = ScriptInterface::ToJSVal(cx, value);
     221                vp.set(ScriptInterface::ToJSVal(cx, value));
    219222                break;
    220223            }
    221224
     
    223226            {
    224227                CStrW value;
    225228                GUI<CStrW>::GetSetting(e, propName, value);
    226                 *vp = ScriptInterface::ToJSVal(cx, value);
     229                vp.set(ScriptInterface::ToJSVal(cx, value));
    227230                break;
    228231            }
    229232
     
    231234            {
    232235                CGUISpriteInstance *value;
    233236                GUI<CGUISpriteInstance>::GetSettingPointer(e, propName, value);
    234                 *vp = ScriptInterface::ToJSVal(cx, value->GetName());
     237                vp.set(ScriptInterface::ToJSVal(cx, value->GetName()));
    235238                break;
    236239            }
    237240
     
    247250                case EAlign_Center: word = "center"; break;
    248251                default: debug_warn(L"Invalid EAlign!"); word = "error"; break;
    249252                }
    250                 *vp = ScriptInterface::ToJSVal(cx, word);
     253                vp.set(ScriptInterface::ToJSVal(cx, word));
    251254                break;
    252255            }
    253256
     
    263266                case EVAlign_Center: word = "center"; break;
    264267                default: debug_warn(L"Invalid EVAlign!"); word = "error"; break;
    265268                }
    266                 *vp = ScriptInterface::ToJSVal(cx, word);
     269                vp.set(ScriptInterface::ToJSVal(cx, word));
    267270                break;
    268271            }
    269272
     
    273276                GUI<CGUIList>::GetSetting(e, propName, value);
    274277
    275278                JSObject *obj = JS_NewArrayObject(cx, 0, NULL);
    276                 *vp = OBJECT_TO_JSVAL(obj); // root it
    277                
     279                vp.set(OBJECT_TO_JSVAL(obj)); // root it
     280
    278281                for (size_t i = 0; i < value.m_Items.size(); ++i)
    279282                {
    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());
    282285                }
    283286
    284287                break;
     
    294297    }
    295298}
    296299
    297 JSBool JSI_IGUIObject::setProperty(JSContext* cx, JSObject* obj, jsid id, JSBool UNUSED(strict), jsval* vp)
     300JSBool JSI_IGUIObject::setProperty(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JSBool UNUSED(strict), JS::MutableHandle<jsval> vp)
    298301{
    299302    IGUIObject* e = (IGUIObject*)JS_GetInstancePrivate(cx, obj, &JSI_IGUIObject::JSI_class, NULL);
    300303    if (!e)
     
    311314    if (propName == "name")
    312315    {
    313316        std::string value;
    314         if (!ScriptInterface::FromJSVal(cx, *vp, value))
     317        if (!ScriptInterface::FromJSVal(cx, vp.get(), value))
    315318            return JS_FALSE;
    316319        e->SetName(value);
    317320        return JS_TRUE;
     
    320323    // Use onWhatever to set event handlers
    321324    if (propName.substr(0, 2) == "on")
    322325    {
    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())))
    324327        {
    325328            JS_ReportError(cx, "on- event-handlers must be functions");
    326329            return JS_FALSE;
    327330        }
    328331
    329332        CStr eventName (CStr(propName.substr(2)).LowerCase());
    330         e->SetScriptHandler(eventName, JSVAL_TO_OBJECT(*vp));
     333        e->SetScriptHandler(eventName, JSVAL_TO_OBJECT(vp.get()));
    331334
    332335        return JS_TRUE;
    333336    }
     
    346349    case GUIST_CStr:
    347350        {
    348351            std::string value;
    349             if (!ScriptInterface::FromJSVal(cx, *vp, value))
     352            if (!ScriptInterface::FromJSVal(cx, vp.get(), value))
    350353                return JS_FALSE;
    351354
    352355            GUI<CStr>::SetSetting(e, propName, value);
     
    356359    case GUIST_CStrW:
    357360        {
    358361            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;
    361364
    362365            GUI<CStrW>::SetSetting(e, propName, value);
    363366            break;
     
    366369    case GUIST_CGUISpriteInstance:
    367370        {
    368371            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;
    371374
    372375            GUI<CGUISpriteInstance>::SetSetting(e, propName, CGUISpriteInstance(value));
    373376            break;
     
    376379    case GUIST_CGUIString:
    377380        {
    378381            std::wstring value;
    379             if (!ScriptInterface::FromJSVal(cx, *vp, value))
     382            if (!ScriptInterface::FromJSVal(cx, vp.get(), value))
    380383                return JS_FALSE;
    381384
    382385            CGUIString str;
     
    388391    case GUIST_EAlign:
    389392        {
    390393            std::string value;
    391             if (!ScriptInterface::FromJSVal(cx, *vp, value))
     394            if (!ScriptInterface::FromJSVal(cx, vp.get(), value))
    392395                return JS_FALSE;
    393396
    394397            EAlign a;
     
    407410    case GUIST_EVAlign:
    408411        {
    409412            std::string value;
    410             if (!ScriptInterface::FromJSVal(cx, *vp, value))
     413            if (!ScriptInterface::FromJSVal(cx, vp.get(), value))
    411414                return JS_FALSE;
    412415
    413416            EVAlign a;
     
    425428
    426429    case GUIST_int:
    427430        {
    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)
    430433                GUI<int>::SetSetting(e, propName, value);
    431434            else
    432435            {
     
    438441
    439442    case GUIST_float:
    440443        {
    441             jsdouble value;
    442             if (JS_ValueToNumber(cx, *vp, &value) == JS_TRUE)
     444            double value;
     445            if (JS_ValueToNumber(cx, vp.get(), &value) == true)
    443446                GUI<float>::SetSetting(e, propName, (float)value);
    444447            else
    445448            {
     
    452455    case GUIST_bool:
    453456        {
    454457            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);
    457460            else
    458461            {
    459462                JS_ReportError(cx, "Cannot convert value to bool");
     
    464467
    465468    case GUIST_CClientArea:
    466469        {
    467             if (JSVAL_IS_STRING(*vp))
     470            if (JSVAL_IS_STRING(vp.get()))
    468471            {
    469472                std::wstring value;
    470                 if (!ScriptInterface::FromJSVal(cx, *vp, value))
     473                if (!ScriptInterface::FromJSVal(cx, vp.get(), value))
    471474                    return JS_FALSE;
    472475
    473476                if (e->SetSetting(propName, value) != PSRETURN_OK)
     
    476479                    return JS_FALSE;
    477480                }
    478481            }
    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))
    480483            {
    481484                CClientArea area;
    482485                GUI<CClientArea>::GetSetting(e, propName, area);
    483486
    484                 JSObject* obj = JSVAL_TO_OBJECT(*vp);
     487                JSObject* obj = JSVAL_TO_OBJECT(vp.get());
    485488                ScriptInterface* pScriptInterface = ScriptInterface::GetScriptInterfaceAndCBData(cx)->pScriptInterface;
    486489                #define P(x, y, z) pScriptInterface->GetProperty(OBJECT_TO_JSVAL(obj), #z, area.x.y)
    487490                    P(pixel,    left,   left);
     
    506509
    507510    case GUIST_CColor:
    508511        {
    509             if (JSVAL_IS_STRING(*vp))
     512            if (JSVAL_IS_STRING(vp.get()))
    510513            {
    511514                std::wstring value;
    512                 if (!ScriptInterface::FromJSVal(cx, *vp, value))
     515                if (!ScriptInterface::FromJSVal(cx, vp.get(), value))
    513516                    return JS_FALSE;
    514517
    515518                if (e->SetSetting(propName, value) != PSRETURN_OK)
     
    518521                    return JS_FALSE;
    519522                }
    520523            }
    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))
    522525            {
    523526                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()); \
    527531                                JS_ValueToNumber(cx, t, &s); \
    528532                                colour.x = (float)s
    529533                PROP(r); PROP(g); PROP(b); PROP(a);
     
    541545
    542546    case GUIST_CGUIList:
    543547        {
    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)
    547551            {
    548552                CGUIList list;
    549553
    550554                for (int i=0; i<(int)length; ++i)
    551555                {
    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()))
    554558                    {
    555559                        JS_ReportError(cx, "Failed to get list element");
    556560                        return JS_FALSE;
     
    562566
    563567                    CGUIString str;
    564568                    str.SetValue(value);
    565                    
     569
    566570                    list.m_Items.push_back(str);
    567571                }
    568572
     
    587591}
    588592
    589593
    590 JSBool JSI_IGUIObject::construct(JSContext* cx, uintN argc, jsval* vp)
     594JSBool JSI_IGUIObject::construct(JSContext* cx, uint argc, jsval* vp)
    591595{
    592596    if (argc == 0)
    593597    {
     
    599603
    600604    // Store the IGUIObject in the JS object's 'private' area
    601605    IGUIObject* guiObject = (IGUIObject*)JSVAL_TO_PRIVATE(JS_ARGV(cx, vp)[0]);
    602     JS_SetPrivate(cx, obj, guiObject);
     606    JS_SetPrivate(obj, guiObject);
    603607
    604608    JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(obj));
    605609    return JS_TRUE;
     
    610614    scriptInterface.DefineCustomObjectType(&JSI_class, construct, 1, JSI_props, JSI_methods, NULL, NULL);
    611615}
    612616
    613 JSBool JSI_IGUIObject::toString(JSContext* cx, uintN argc, jsval* vp)
     617JSBool JSI_IGUIObject::toString(JSContext* cx, uint argc, jsval* vp)
    614618{
    615619    UNUSED2(argc);
    616620
     
    625629    return JS_TRUE;
    626630}
    627631
    628 JSBool JSI_IGUIObject::focus(JSContext* cx, uintN argc, jsval* vp)
     632JSBool JSI_IGUIObject::focus(JSContext* cx, uint argc, jsval* vp)
    629633{
    630634    UNUSED2(argc);
    631635
     
    639643    return JS_TRUE;
    640644}
    641645
    642 JSBool JSI_IGUIObject::blur(JSContext* cx, uintN argc, jsval* vp)
     646JSBool JSI_IGUIObject::blur(JSContext* cx, uint argc, jsval* vp)
    643647{
    644648    UNUSED2(argc);
    645649
     
    653657    return JS_TRUE;
    654658}
    655659
    656 JSBool JSI_IGUIObject::getComputedSize(JSContext* cx, uintN argc, jsval* vp)
     660JSBool JSI_IGUIObject::getComputedSize(JSContext* cx, uint argc, jsval* vp)
    657661{
    658662    UNUSED2(argc);
    659663    IGUIObject* e = (IGUIObject*)JS_GetInstancePrivate(cx, JS_THIS_OBJECT(cx, vp), &JSI_IGUIObject::JSI_class, NULL);
  • source/gui/scripting/JSInterface_IGUIObject.h

     
    2525    extern JSClass JSI_class;
    2626    extern JSPropertySpec JSI_props[];
    2727    extern JSFunctionSpec JSI_methods[];
    28     JSBool getProperty(JSContext* cx, JSObject* obj, jsid id, jsval* vp);
    29     JSBool setProperty(JSContext* cx, JSObject* obj, jsid id, JSBool strict, jsval* vp);
    30     JSBool construct(JSContext* cx, uintN argc, jsval* vp);
    31     JSBool toString(JSContext* cx, uintN argc, jsval* vp);
    32     JSBool focus(JSContext* cx, uintN argc, jsval* vp);
    33     JSBool blur(JSContext* cx, uintN argc, jsval* vp);
    34     JSBool getComputedSize(JSContext* cx, uintN argc, 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);
    3535    void init(ScriptInterface& scriptInterface);
    3636}
    3737
  • source/gui/scripting/ScriptFunctions.cpp

     
    6969#include "soundmanager/SoundManager.h"
    7070#include "soundmanager/scripting/JSInterface_Sound.h"
    7171
    72 #include "js/jsapi.h"
    7372/*
    7473 * This file defines a set of functions that are available to GUI scripts, to allow
    7574 * interaction with the rest of the engine.
     
    557556void ForceGC(ScriptInterface::CxPrivate* pCxPrivate)
    558557{
    559558    double time = timer_Time();
    560     JS_GC(pCxPrivate->pScriptInterface->GetContext());
     559    JS_GC(pCxPrivate->pScriptInterface->GetJSRuntime());
    561560    time = timer_Time() - time;
    562561    g_Console->InsertMessage(L"Garbage collection completed in: %f", time);
    563562}
  • source/lib/types.h

     
    3333
    3434#define i8 int8_t
    3535#define i16 int16_t
    36 #define i32 int32_t
     36//#define i32 int32_t
     37typedef int32_t i32;
    3738#define i64 int64_t
    3839
    3940#define u8  uint8_t
    40 #define u16 uint16_t
    41 #define u32 uint32_t
     41//#define u16 uint16_t
     42typedef uint16_t u16;
     43//#define u32 uint32_t
     44typedef uint32_t u32;
    4245#define u64 uint64_t
    4346
    4447#endif // #ifndef INCLUDED_TYPES
  • source/lobby/XmppClient.cpp

     
    309309void XmppClient::SendIqGameReport(ScriptInterface& scriptInterface, CScriptVal data)
    310310{
    311311    glooxwrapper::JID xpartamuppJid(m_xpartamuppId);
    312     jsval dataval = data.get();
     312    JS::RootedValue dataval(scriptInterface.GetContext(), data.get());
    313313
    314314    // Setup some base stanza attributes
    315315    GameReport* game = new GameReport();
     
    317317
    318318    // Iterate through all the properties reported and add them to the stanza.
    319319    std::vector<std::string> properties;
    320     scriptInterface.EnumeratePropertyNamesWithPrefix(dataval, "", properties);
     320    scriptInterface.EnumeratePropertyNamesWithPrefix(JS::RootedObject(scriptInterface.GetContext(), JSVAL_TO_OBJECT(dataval)), "", properties);
    321321    for (std::vector<int>::size_type i = 0; i != properties.size(); i++)
    322322    {
    323323        std::wstring value;
     
    343343void XmppClient::SendIqRegisterGame(ScriptInterface& scriptInterface, CScriptVal data)
    344344{
    345345    glooxwrapper::JID xpartamuppJid(m_xpartamuppId);
    346     jsval dataval = data.get();
     346    JS::RootedValue dataval(scriptInterface.GetContext(), data.get());
    347347
    348348    // Setup some base stanza attributes
    349349    GameListQuery* g = new GameListQuery();
     
    354354
    355355    // Iterate through all the properties reported and add them to the stanza.
    356356    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);
    358359    for (std::vector<int>::size_type i = 0; i != properties.size(); i++)
    359360    {
    360361        std::wstring value;
  • source/ps/Errors.h

     
    7272
    7373#include <exception>
    7474
    75 typedef u32 PSRETURN;
     75//typedef u32 PSRETURN;
     76typedef uint32_t PSRETURN;
    7677
    7778class PSERROR : public std::exception
    7879{
  • source/ps/GameSetup/GameSetup.cpp

     
    560560    SAFE_DELETE(g_GUI);
    561561
    562562    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();
    563567
    564568    // disable the special Windows cursor, or free textures for OGL cursors
    565569    cursor_draw(g_VFS, 0, g_mouse_x, g_yres-g_mouse_y, false);
     
    858862    g_Logger = new CLogger;
    859863   
    860864    // 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);
    862866
    863867    // Special command-line mode to dump the entity schemas instead of running the game.
    864868    // (This must be done after loading VFS etc, but should be done before wasting time
     
    11041108        CStr seedArg = args.Get("autostart-random");
    11051109
    11061110        // Default seed is 0
    1107         uint32 seed = 0;
     1111        uint32_t seed = 0;
    11081112        if (!seedArg.empty())
    11091113        {
    11101114            if (seedArg.compare("-1") == 0)
  • source/ps/Profile.cpp

     
    2929# define USE_CRT_SET_ALLOC_HOOK
    3030#endif
    3131
    32 #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
     32//#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
    3939
    4040#include <numeric>
    4141
     
    287287{
    288288    if (collection.empty())
    289289        return 0.0;
     290    //return collection[collection.size()-1];
    290291    return std::accumulate(collection.begin(), collection.end(), 0.0) / collection.size();
    291292}
    292293
  • source/ps/Replay.cpp

     
    127127    new CProfileManager;
    128128    g_ScriptStatsTable = new CScriptStatsTable;
    129129    g_ProfileViewer.AddRootTable(g_ScriptStatsTable);
    130     g_ScriptRuntime = ScriptInterface::CreateRuntime(128 * 1024 * 1024);
     130    g_ScriptRuntime = ScriptInterface::CreateRuntime(384 * 1024 * 1024);
    131131
    132132    CGame game(true);
    133133    g_Game = &game;
     
    210210                g_Profiler2.IncrementFrameNumber();
    211211                PROFILE2_ATTR("%d", g_Profiler2.GetFrameNumber());
    212212
     213                game.GetSimulation2()->Tick();
    213214                game.GetSimulation2()->Update(turnLength, commands);
    214215                commands.clear();
    215216            }
    216217
    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());
    221222
    222223            debug_printf(L"\n");
    223224
     
    244245
    245246    timer_DisplayClientTotals();
    246247
     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   
    247252    // Clean up
    248253    delete &g_TexMan;
    249254    tex_codec_unregister_all();
  • source/ps/scripting/JSInterface_VFS.cpp

     
    6868{
    6969    BuildDirEntListState* s = (BuildDirEntListState*)cbData;
    7070
    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());
    7373    return INFO::OK;
    7474}
    7575
     
    191191    while (std::getline(ss, line))
    192192    {
    193193        // 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());
    196196    }
    197197
    198198    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 modify
    5  * it under the terms of the GNU General Public License as published by
    6  * the Free Software Foundation, either version 2 of the License, or
    7  * (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 of
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12  * GNU General Public License for more details.
    13  *
    14  * You should have received a copy of the GNU General Public License
    15  * 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 SpiderMonkey
    30     // 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 modify
    5  * it under the terms of the GNU General Public License as published by
    6  * the Free Software Foundation, either version 2 of the License, or
    7  * (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 of
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12  * GNU General Public License for more details.
    13  *
    14  * You should have received a copy of the GNU General Public License
    15  * along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
    16  */
    17 
    18 // included from SpiderMonkey.h
    19 
    20 extern JSBool jsu_report_param_error(JSContext* cx, jsval* vp);
    21 
    22 
    23 // consistent argc checking for normal function wrappers: reports an
    24 // 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 count
    38 #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 are
    47 // a bit further removed from SpiderMonkey, i.e. return a
    48 // 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

     
    3535
    3636#include "scriptinterface/ScriptTypes.h"
    3737
    38 #include "JSUtil.h"
    39 
    4038// Make JS debugging a little easier by automatically naming GC roots
    4139// Don't simply #define NAME_ALL_GC_ROOTS, because jsapi.h is horridly broken
    4240#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 modify
    5  * it under the terms of the GNU General Public License as published by
    6  * the Free Software Foundation, either version 2 of the License, or
    7  * (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 of
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12  * GNU General Public License for more details.
    13  *
    14  * You should have received a copy of the GNU General Public License
    15  * 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 nested
    34 }
    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 modify
    5  * it under the terms of the GNU General Public License as published by
    6  * the Free Software Foundation, either version 2 of the License, or
    7  * (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 of
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12  * GNU General Public License for more details.
    13  *
    14  * You should have received a copy of the GNU General Public License
    15  * along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
    16  */
    17 
    18 #ifndef INCLUDED_AUTOROOTERS
    19 #define INCLUDED_AUTOROOTERS
    20 
    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 this
    28  * object is destroyed.
    29  * Many of these objects can be used at once, but their lifetimes must be correctly nested.
    30  */
    31 class AutoGCRooter
    32 {
    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 types
    51 };
    52 
    53 #endif // INCLUDED_AUTOROOTERS
  • source/scriptinterface/NativeWrapperDecls.h

     
    2626#define NUMBERED_LIST_BALANCED(z, i, data) BOOST_PP_COMMA_IF(i) data##i
    2727// Some other things
    2828#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;
    3030
    3131// List-generating macros, named roughly after their first list item
    3232#define TYPENAME_T0_HEAD(z, i) BOOST_PP_REPEAT_##z (i, NUMBERED_LIST_HEAD, typename T) // "typename T0, typename T1, "
     
    5151// (Definition comes later, since it depends on some things we haven't defined yet)
    5252#define OVERLOADS(z, i, data) \
    5353    template <typename R, TYPENAME_T0_HEAD(z,i)  R (*fptr) ( ScriptInterface::CxPrivate* T0_TAIL(z,i) )> \
    54     static JSBool call(JSContext* cx, uintN argc, jsval* vp);
     54    static JSBool call(JSContext* cx, uint32_t argc, jsval* vp);
    5555BOOST_PP_REPEAT(SCRIPT_INTERFACE_MAX_ARGS, OVERLOADS, ~)
    5656#undef OVERLOADS
    5757
    5858// Similar, for class methods
    5959#define OVERLOADS(z, i, data) \
    6060    template <typename R, TYPENAME_T0_HEAD(z,i)  JSClass* CLS, typename TC, R (TC::*fptr) ( T0(z,i) )> \
    61     static JSBool callMethod(JSContext* cx, uintN argc, jsval* vp);
     61    static JSBool callMethod(JSContext* cx, uint32_t argc, jsval* vp);
    6262BOOST_PP_REPEAT(SCRIPT_INTERFACE_MAX_ARGS, OVERLOADS, ~)
    6363#undef OVERLOADS
    6464
  • source/scriptinterface/NativeWrapperDefns.h

     
    7979#define SCRIPT_PROFILE \
    8080    if (g_ScriptProfilingEnabled) \
    8181    { \
    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)))); \
    8383        const char* name = "(unknown)"; \
    8484        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)) \
    8787            name = static_cast<const char*>(JSVAL_TO_PRIVATE(nameval)); \
    8888        CProfileSampleScript profile(name); \
    8989    }
     
    9191// JSFastNative-compatible function that wraps the function identified in the template argument list
    9292#define OVERLOADS(z, i, data) \
    9393    template <typename R, TYPENAME_T0_HEAD(z,i)  R (*fptr) ( ScriptInterface::CxPrivate* T0_TAIL(z,i) )> \
    94     JSBool ScriptInterface::call(JSContext* cx, uintN argc, jsval* vp) { \
     94    JSBool ScriptInterface::call(JSContext* cx, uint32_t argc, jsval* vp) { \
    9595        UNUSED2(argc); \
    9696        SCRIPT_PROFILE \
    9797        BOOST_PP_REPEAT_##z (i, CONVERT_ARG, ~) \
    9898        jsval rval = JSVAL_VOID; \
    9999        ScriptInterface_NativeWrapper<R>::call(cx, rval, fptr  A0_TAIL(z,i)); \
    100100        JS_SET_RVAL(cx, vp, rval); \
    101         return (ScriptInterface::IsExceptionPending(cx) ? JS_FALSE : JS_TRUE); \
     101        return !ScriptInterface::IsExceptionPending(cx); \
    102102    }
    103103BOOST_PP_REPEAT(SCRIPT_INTERFACE_MAX_ARGS, OVERLOADS, ~)
    104104#undef OVERLOADS
     
    106106// Same idea but for methods
    107107#define OVERLOADS(z, i, data) \
    108108    template <typename R, TYPENAME_T0_HEAD(z,i)  JSClass* CLS, typename TC, R (TC::*fptr) ( T0(z,i) )> \
    109     JSBool ScriptInterface::callMethod(JSContext* cx, uintN argc, jsval* vp) { \
     109    JSBool ScriptInterface::callMethod(JSContext* cx, uint32_t argc, jsval* vp) { \
    110110        UNUSED2(argc); \
    111111        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; \
    115115        BOOST_PP_REPEAT_##z (i, CONVERT_ARG, ~) \
    116116        jsval rval = JSVAL_VOID; \
    117117        ScriptInterface_NativeMethodWrapper<R, TC>::call(cx, rval, c, fptr  A0_TAIL(z,i)); \
    118118        JS_SET_RVAL(cx, vp, rval); \
    119         return (ScriptInterface::IsExceptionPending(cx) ? JS_FALSE : JS_TRUE); \
     119        return !ScriptInterface::IsExceptionPending(cx); \
    120120    }
    121121BOOST_PP_REPEAT(SCRIPT_INTERFACE_MAX_ARGS, OVERLOADS, ~)
    122122#undef OVERLOADS
  • source/scriptinterface/ScriptConversions.cpp

     
    3232
    3333template<> bool ScriptInterface::FromJSVal<bool>(JSContext* cx, jsval v, bool& out)
    3434{
     35    JSAutoRequest rq(cx);
    3536    JSBool ret;
    3637    WARN_IF_NOT(JSVAL_IS_BOOLEAN(v), v);
    3738    if (!JS_ValueToBoolean(cx, v, &ret))
     
    4243
    4344template<> bool ScriptInterface::FromJSVal<float>(JSContext* cx, jsval v, float& out)
    4445{
    45     jsdouble ret;
     46    JSAutoRequest rq(cx);
     47    double ret;
    4648    WARN_IF_NOT(JSVAL_IS_NUMBER(v), v);
    4749    if (!JS_ValueToNumber(cx, v, &ret))
    4850        return false;
     
    5254
    5355template<> bool ScriptInterface::FromJSVal<double>(JSContext* cx, jsval v, double& out)
    5456{
    55     jsdouble ret;
     57    JSAutoRequest rq(cx);
     58    double ret;
    5659    WARN_IF_NOT(JSVAL_IS_NUMBER(v), v);
    5760    if (!JS_ValueToNumber(cx, v, &ret))
    5861        return false;
     
    6265
    6366template<> bool ScriptInterface::FromJSVal<i32>(JSContext* cx, jsval v, i32& out)
    6467{
    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;
    6672    WARN_IF_NOT(JSVAL_IS_NUMBER(v), v);
    67     if (!JS_ValueToECMAInt32(cx, v, &ret))
     73    if (!JS::ToInt32(cx, v1, &ret))
    6874        return false;
    6975    out = ret;
    7076    return true;
     
    7278
    7379template<> bool ScriptInterface::FromJSVal<u32>(JSContext* cx, jsval v, u32& out)
    7480{
    75     uint32 ret;
     81    JSAutoRequest rq(cx);
     82    uint32_t ret;
    7683    WARN_IF_NOT(JSVAL_IS_NUMBER(v), v);
    7784    if (!JS_ValueToECMAUint32(cx, v, &ret))
    7885        return false;
     
    8289
    8390template<> bool ScriptInterface::FromJSVal<u16>(JSContext* cx, jsval v, u16& out)
    8491{
    85     uint16 ret;
     92    JSAutoRequest rq(cx);
     93    uint16_t ret;
    8694    WARN_IF_NOT(JSVAL_IS_NUMBER(v), v);
    8795    if (!JS_ValueToUint16(cx, v, &ret))
    8896        return false;
     
    92100
    93101template<> bool ScriptInterface::FromJSVal<u8>(JSContext* cx, jsval v, u8& out)
    94102{
    95     uint16 ret;
     103    JSAutoRequest rq(cx);
     104    uint16_t ret;
    96105    WARN_IF_NOT(JSVAL_IS_NUMBER(v), v);
    97106    if (!JS_ValueToUint16(cx, v, &ret))
    98107        return false;
     
    102111
    103112template<> bool ScriptInterface::FromJSVal<long>(JSContext* cx, jsval v, long& out)
    104113{
    105     int32 tmp;
    106     JSBool ok = JS_ValueToInt32(cx, v, &tmp);
     114    int32_t tmp;
     115    bool ok = JS_ValueToInt32(cx, v, &tmp);
    107116    out = (long)tmp;
    108     return ok == JS_TRUE;
     117    return ok;
    109118}
    110119
    111120template<> bool ScriptInterface::FromJSVal<unsigned long>(JSContext* cx, jsval v, unsigned long& out)
    112121{
    113     int32 tmp;
    114     JSBool ok = JS_ValueToInt32(cx, v, &tmp);
     122    int32_t tmp;
     123    bool ok = JS_ValueToInt32(cx, v, &tmp);
    115124    out = (unsigned long)tmp;
    116     return ok == JS_TRUE;
     125    return ok;
    117126}
    118127
    119128// see comment below (where the same preprocessor condition is used)
     
    143152
    144153#endif
    145154
    146 // NOTE: we can't define a jsval specialisation, because that conflicts with integer types
     155template<> jsval ScriptInterface::ToJSVal<JS::Value>(JSContext* UNUSED(cx), const JS::Value& val)
     156{
     157    return val;
     158}
     159
    147160template<> bool ScriptInterface::FromJSVal<CScriptVal>(JSContext* UNUSED(cx), jsval v, CScriptVal& out)
    148161{
    149162    out = v;
    150163    return true;
    151164}
    152165
     166template<> 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
    153176template<> bool ScriptInterface::FromJSVal<CScriptValRooted>(JSContext* cx, jsval v, CScriptValRooted& out)
    154177{
    155178    out = CScriptValRooted(cx, v);
     
    158181
    159182template<> bool ScriptInterface::FromJSVal<std::wstring>(JSContext* cx, jsval v, std::wstring& out)
    160183{
     184    JSAutoRequest rq(cx);
    161185    WARN_IF_NOT(JSVAL_IS_STRING(v) || JSVAL_IS_NUMBER(v), v); // allow implicit number conversions
    162186    JSString* ret = JS_ValueToString(cx, v);
    163187    if (!ret)
     
    181205
    182206template<> bool ScriptInterface::FromJSVal<std::string>(JSContext* cx, jsval v, std::string& out)
    183207{
     208    JSAutoRequest rq(cx);
    184209    WARN_IF_NOT(JSVAL_IS_STRING(v) || JSVAL_IS_NUMBER(v), v); // allow implicit number conversions
    185210    JSString* ret = JS_ValueToString(cx, v);
    186211    if (!ret)
     
    205230
    206231template<> bool ScriptInterface::FromJSVal<Entity>(JSContext* cx, jsval v, Entity& out)
    207232{
     233    JSAutoRequest rq(cx);
    208234    JSObject* obj;
    209235    if (!JS_ValueToObject(cx, v, &obj) || obj == NULL)
    210236        FAIL("Argument must be an object");
    211237
    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);
    213243
    214244    // 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))
    216246        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))
    218248        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))
    220250        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))
    222252        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))
    224254        FAIL("Failed to read Entity.rotation property");
    225255
    226256    return true;
     
    234264    return val ? JSVAL_TRUE : JSVAL_FALSE;
    235265}
    236266
    237 template<> jsval ScriptInterface::ToJSVal<float>(JSContext* cx, const float& val)
     267template<> jsval ScriptInterface::ToJSVal<float>(JSContext* UNUSED(cx), const float& val)
    238268{
    239     jsval rval = JSVAL_VOID;
    240     JS_NewNumberValue(cx, val, &rval); // ignore return value
     269    jsval rval = JS_NumberValue(val);
    241270    return rval;
    242271}
    243272
    244 template<> jsval ScriptInterface::ToJSVal<double>(JSContext* cx, const double& val)
     273template<> jsval ScriptInterface::ToJSVal<double>(JSContext* UNUSED(cx), const double& val)
    245274{
    246     jsval rval = JSVAL_VOID;
    247     JS_NewNumberValue(cx, val, &rval); // ignore return value
     275    jsval rval = JS_NumberValue(val);
    248276    return rval;
    249277}
    250278
     
    264292    return INT_TO_JSVAL(val);
    265293}
    266294
    267 template<> jsval ScriptInterface::ToJSVal<u32>(JSContext* cx, const u32& val)
     295template<> jsval ScriptInterface::ToJSVal<u32>(JSContext* UNUSED(cx), const u32& val)
    268296{
    269297    if (val <= JSVAL_INT_MAX)
    270298        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);
    273300    return rval;
    274301}
    275302
     
    315342
    316343template<> jsval ScriptInterface::ToJSVal<std::wstring>(JSContext* cx, const std::wstring& val)
    317344{
     345    JSAutoRequest rq(cx);
    318346    utf16string utf16(val.begin(), val.end());
    319347    JSString* str = JS_NewUCStringCopyN(cx, reinterpret_cast<const jschar*> (utf16.c_str()), utf16.length());
    320348    if (str)
     
    329357
    330358template<> jsval ScriptInterface::ToJSVal<std::string>(JSContext* cx, const std::string& val)
    331359{
     360    JSAutoRequest rq(cx);
    332361    JSString* str = JS_NewStringCopyN(cx, val.c_str(), val.length());
    333362    if (str)
    334363        return STRING_TO_JSVAL(str);
     
    342371
    343372template<> jsval ScriptInterface::ToJSVal<const char*>(JSContext* cx, const char* const& val)
    344373{
     374    JSAutoRequest rq(cx);
    345375    JSString* str = JS_NewStringCopyZ(cx, val);
    346376    if (str)
    347377        return STRING_TO_JSVAL(str);
     
    363393
    364394template<typename T> static jsval ToJSVal_vector(JSContext* cx, const std::vector<T>& val)
    365395{
    366     JSObject* obj = JS_NewArrayObject(cx, (jsint)val.size(), NULL);
     396    JSAutoRequest rq(cx);
     397    JSObject* obj = JS_NewArrayObject(cx, val.size(), NULL);
    367398    if (!obj)
    368399        return JSVAL_VOID;
    369     for (size_t i = 0; i < val.size(); ++i)
     400    for (uint32_t i = 0; i < val.size(); ++i)
    370401    {
    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());
    373404    }
    374405    return OBJECT_TO_JSVAL(obj);
    375406}
    376407
    377408template<typename T> static bool FromJSVal_vector(JSContext* cx, jsval v, std::vector<T>& out)
    378409{
     410    JSAutoRequest rq(cx);
    379411    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)))
    381413        FAIL("Argument must be an array");
    382     jsuint length;
     414    uint32_t length;
    383415    if (!JS_GetArrayLength(cx, obj, &length))
    384416        FAIL("Failed to get array length");
    385417    out.reserve(length);
    386     for (jsuint i = 0; i < length; ++i)
     418    for (uint32_t i = 0; i < length; ++i)
    387419    {
    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()))
    390422            FAIL("Failed to read array element");
    391423        T el2;
    392424        if (!ScriptInterface::FromJSVal<T>(cx, el, el2))
  • source/scriptinterface/ScriptExtraHeaders.h

     
    2525#include "scriptinterface/ScriptTypes.h"
    2626
    2727// 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
    2934# if GCC_VERSION >= 406 // store user flags
    3035#  pragma GCC diagnostic push
    3136# endif
    3237# pragma GCC diagnostic ignored "-Wunused-parameter"
    3338# pragma GCC diagnostic ignored "-Wredundant-decls"
    34 # if GCC_VERSION >= 408
     39# pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
     40# if GCC_VERSION >= 407
    3541#  pragma GCC diagnostic ignored "-Wunused-local-typedefs" // caused by js/debug.h
    3642# endif
    3743#endif
     
    4652# define signbit std::signbit
    4753#endif
    4854
    49 #include "js/jstypedarray.h"
    50 #include "js/jsdbgapi.h"
     55#include "jsfriendapi.h"
     56#include "jsdbgapi.h"
     57#include "js/GCAPI.h"
    5158
    5259#undef signbit
    5360
     
    5764#if GCC_VERSION >= 402
    5865# pragma GCC diagnostic warning "-Wunused-parameter"
    5966# 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
    6071# if GCC_VERSION >= 406
    6172#  pragma GCC diagnostic pop // restore user flags
    6273# endif
  • source/scriptinterface/ScriptInterface.cpp

     
    2020#include "ScriptInterface.h"
    2121// #include "DebuggingServer.h" // JS debugger temporarily disabled during the SpiderMonkey upgrade (check trac ticket #2348 for details)
    2222#include "ScriptStats.h"
    23 #include "AutoRooters.h"
    2423
    2524#include "lib/debug.h"
    2625#include "lib/utf8.h"
     
    4746
    4847#include "scriptinterface/ScriptExtraHeaders.h"
    4948
     49
    5050/**
    5151 * @file
    5252 * Abstractions of various SpiderMonkey features.
     
    6565 * (One means to share data between threads and runtimes is to create
    6666 * a ScriptInterface::StructuredClone.)
    6767 */
     68
     69
     70void 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 
    68135class ScriptRuntime
    69136{
    70137public:
    71     ScriptRuntime(int runtimeSize) :
    72         m_rooter(NULL)
     138    ScriptRuntime(int runtimeSize):
     139        m_LastGCBytes(0)
    73140    {
    74         m_rt = JS_NewRuntime(runtimeSize);
     141        m_rt = JS_NewRuntime(runtimeSize, JS_USE_HELPER_THREADS);
     142
    75143        ENSURE(m_rt); // TODO: error handling
    76144
     145        JS_SetNativeStackQuota(m_rt, 128 * sizeof(size_t) * 1024);
    77146        if (g_ScriptProfilingEnabled)
    78147        {
    79148            // Profiler isn't thread-safe, so only enable this on the main thread
     
    86155                }
    87156            }
    88157        }
     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);
    89170
    90         JS_SetExtraGCRoots(m_rt, jshook_trace, this);
     171        m_dummyContext = JS_NewContext(m_rt, STACK_CHUNK_SIZE);
     172        ENSURE(m_dummyContext);
    91173    }
     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    }
    92220
    93221    ~ScriptRuntime()
    94222    {
     223        JS_DestroyContext(m_dummyContext);
    95224        JS_DestroyRuntime(m_rt);
    96225    }
    97 
     226   
     227    // Workaround for: https://bugzilla.mozilla.org/show_bug.cgi?id=890243
     228    JSContext* m_dummyContext;
     229   
    98230    JSRuntime* m_rt;
    99     AutoGCRooter* m_rooter;
    100231
    101232private:
     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;
    102245
    103246
    104     static void* jshook_script(JSContext* UNUSED(cx), JSStackFrame* 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)
    105248    {
    106249        if (before)
    107250            g_Profiler.StartScript("script invocation");
     
    154297            if (slash != filename.npos)
    155298                filename = filename.substr(slash+1);
    156299
    157             uintN line = JS_PCToLineNumber(cx, script, pc);
     300            uint line = JS_PCToLineNumber(cx, script, pc);
    158301
    159302            std::stringstream ss;
    160303            ss << "(" << filename << ":" << line << ")";
     
    178321        boost::flyweights::no_locking
    179322    > LocFlyweight;
    180323
    181     static void* jshook_function(JSContext* cx, JSStackFrame* 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)
    182325    {
    183326        if (!before)
    184327        {
     
    186329            return closure;
    187330        }
    188331
    189         JSFunction* fn = JS_GetFrameFunction(cx, fp);
     332        JSFunction* fn = fp.maybeFun();
    190333        if (!fn)
    191334        {
    192335            g_Profiler.StartScript("(function)");
     
    207350        }
    208351
    209352        // 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) };
    211358        g_Profiler.StartScript(LocFlyweight(loc).get().name.c_str());
    212359
    213360        return closure;
    214361    }
    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     }
    223362};
    224363
    225364shared_ptr<ScriptRuntime> ScriptInterface::CreateRuntime(int runtimeSize)
     
    233372{
    234373    ScriptInterface_impl(const char* nativeScopeName, const shared_ptr<ScriptRuntime>& runtime);
    235374    ~ScriptInterface_impl();
    236     void Register(const char* name, JSNative fptr, uintN nargs);
     375    void Register(const char* name, JSNative fptr, uint nargs);
    237376
    238377    shared_ptr<ScriptRuntime> m_runtime;
    239378    JSContext* m_cx;
    240379    JSObject* m_glob; // global scope object
     380    JSCompartment* m_comp;
     381    boost::rand48* m_rng;
    241382    JSObject* m_nativeScope; // native function scope object
    242383
    243384    typedef std::map<ScriptInterface::CACHED_VAL, CScriptValRooted> ScriptValCache;
     
    249390
    250391JSClass global_class = {
    251392    "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,
    255397    NULL, NULL, NULL, NULL
    256398};
    257399
    258400void ErrorReporter(JSContext* cx, const char* message, JSErrorReport* report)
    259401{
    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, so
    262     // ignore that specific warning here
    263     if (report->flags == 5 && report->lineno == 0 && report->errorNumber == 163)
    264         return;
    265402
    266403    std::stringstream msg;
    267404    bool isWarning = JSREPORT_IS_WARNING(report->flags);
     
    276413
    277414    // If there is an exception, then print its stack trace
    278415    jsval excn;
    279     if (JS_GetPendingException(cx, &excn) && JSVAL_IS_OBJECT(excn))
     416    if (JS_GetPendingException(cx, &excn) && !JSVAL_IS_PRIMITIVE(excn))
    280417    {
    281418        // TODO: this violates the docs ("The error reporter callback must not reenter the JSAPI.")
    282419
     
    312449
    313450// Functions in the global namespace:
    314451
    315 JSBool print(JSContext* cx, uintN argc, jsval* vp)
     452JSBool print(JSContext* cx, uint argc, jsval* vp)
    316453{
    317     for (uintN i = 0; i < argc; ++i)
     454    for (uint i = 0; i < argc; ++i)
    318455    {
    319456        std::wstring str;
    320457        if (!ScriptInterface::FromJSVal(cx, JS_ARGV(cx, vp)[i], str))
     
    326463    return JS_TRUE;
    327464}
    328465
    329 JSBool logmsg(JSContext* cx, uintN argc, jsval* vp)
     466JSBool logmsg(JSContext* cx, uint argc, jsval* vp)
    330467{
    331468    if (argc < 1)
    332469    {
     
    337474    std::wstring str;
    338475    if (!ScriptInterface::FromJSVal(cx, JS_ARGV(cx, vp)[0], str))
    339476        return JS_FALSE;
    340     LOGMESSAGE(L"%ls", str.c_str());
     477    LOGMESSAGE(L"%ls%f", str.c_str(), timer_Time());
    341478    JS_SET_RVAL(cx, vp, JSVAL_VOID);
    342479    return JS_TRUE;
    343480}
    344481
    345 JSBool warn(JSContext* cx, uintN argc, jsval* vp)
     482JSBool warn(JSContext* cx, uint argc, jsval* vp)
    346483{
    347484    if (argc < 1)
    348485    {
     
    358495    return JS_TRUE;
    359496}
    360497
    361 JSBool error(JSContext* cx, uintN argc, jsval* vp)
     498JSBool error(JSContext* cx, uint argc, jsval* vp)
    362499{
    363500    if (argc < 1)
    364501    {
     
    374511    return JS_TRUE;
    375512}
    376513
    377 JSBool deepcopy(JSContext* cx, uintN argc, jsval* vp)
     514JSBool deepcopy(JSContext* cx, uint argc, jsval* vp)
    378515{
    379516    if (argc < 1)
    380517    {
     
    384521
    385522    jsval ret;
    386523
    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))
    395525        return JS_FALSE;
    396526
    397527    JS_SET_RVAL(cx, vp, ret);
    398528    return JS_TRUE;
    399529}
    400530
    401 JSBool ProfileStart(JSContext* cx, uintN argc, jsval* vp)
     531JSBool ProfileStart(JSContext* cx, uint argc, jsval* vp)
    402532{
    403533    const char* name = "(ProfileStart)";
    404534
     
    421551        g_Profiler.StartScript(name);
    422552
    423553    g_Profiler2.RecordRegionEnter(name);
    424 
     554   
    425555    JS_SET_RVAL(cx, vp, JSVAL_VOID);
    426556    return JS_TRUE;
    427557}
    428558
    429 JSBool ProfileStop(JSContext* UNUSED(cx), uintN UNUSED(argc), jsval* vp)
     559JSBool ProfileStop(JSContext* UNUSED(cx), uint UNUSED(argc), jsval* vp)
    430560{
    431561    if (CProfileManager::IsInitialised() && ThreadUtil::IsMainThread())
    432562        g_Profiler.Stop();
     
    455585    }
    456586}
    457587
    458 JSBool Math_random(JSContext* cx, uintN UNUSED(argc), jsval* vp)
     588JSBool Math_random(JSContext* cx, uint UNUSED(argc), jsval* vp)
    459589{
    460     // Grab the RNG that was hidden in our slot
    461     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    {
    463593        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}
    465602
    466     double r = generate_uniform_real(*rng, 0.0, 1.0);
     603} // anonymous namespace
    467604
    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;
     605bool 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;
    473611}
    474612
    475 } // anonymous namespace
    476 
    477613ScriptInterface_impl::ScriptInterface_impl(const char* nativeScopeName, const shared_ptr<ScriptRuntime>& runtime) :
    478614    m_runtime(runtime)
    479615{
    480     JSBool ok;
     616    bool ok;
    481617
    482618    m_cx = JS_NewContext(m_runtime->m_rt, STACK_CHUNK_SIZE);
    483619    ENSURE(m_cx);
    484620
     621    JS_SetParallelCompilationEnabled(m_cx, true);
     622
    485623    // For GC debugging:
    486624    // JS_SetGCZeal(m_cx, 2);
    487625
    488626    JS_SetContextPrivate(m_cx, NULL);
    489627
    490628    JS_SetErrorReporter(m_cx, ErrorReporter);
     629   
    491630
    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"
    495637    options |= JSOPTION_VAROBJFIX; // "recommended" (fixes variable scoping)
    496638
    497639    // Enable method JIT, unless script profiling/debugging is enabled (since profiling/debugging
     
    499641    // TODO: Verify what exactly is incompatible
    500642    if (!g_ScriptProfilingEnabled && !g_JSDebuggerEnabled)
    501643    {
    502         options |= JSOPTION_METHODJIT;
     644        options |= JSOPTION_BASELINE;
     645        options |= JSOPTION_ION;
     646        options |= JSOPTION_TYPE_INFERENCE;
     647        options |= JSOPTION_COMPILE_N_GO;
    503648
    504649        // Some other JIT flags to experiment with:
    505         options |= JSOPTION_JIT;
    506         options |= JSOPTION_PROFILING;
     650        //options |= JSOPTION_METHODJIT_ALWAYS;
    507651    }
    508652
    509653    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);
    511662
    512     m_glob = JS_NewCompartmentAndGlobalObject(m_cx, &global_class, NULL);
    513 
    514663    ok = JS_InitStandardClasses(m_cx, m_glob);
    515664    ENSURE(ok);
     665   
     666    //JS_SetVersionForCompartment(m_comp, JSVERSION_LATEST);
    516667
     668
    517669    JS_DefineProperty(m_cx, m_glob, "global", OBJECT_TO_JSVAL(m_glob), NULL, NULL, JSPROP_ENUMERATE | JSPROP_READONLY
    518670            | JSPROP_PERMANENT);
    519671
     
    528680
    529681    Register("ProfileStart", ::ProfileStart, 1);
    530682    Register("ProfileStop", ::ProfileStop, 0);
     683   
     684    runtime->RegisterContext(m_cx);
    531685}
    532686
    533687ScriptInterface_impl::~ScriptInterface_impl()
    534688{
    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    }
    538698    JS_DestroyContext(m_cx);
    539699}
    540700
    541 void ScriptInterface_impl::Register(const char* name, JSNative fptr, uintN nargs)
     701void ScriptInterface_impl::Register(const char* name, JSNative fptr, uint nargs)
    542702{
     703    JSAutoRequest rq(m_cx);
    543704    JSFunction* func = JS_DefineFunction(m_cx, m_nativeScope, name, fptr, nargs, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT);
    544705
    545706    if (!func)
     
    558719        > LockedStringFlyweight;
    559720
    560721        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()));
    562723    }
    563724}
    564725
     
    605766    JS_ShutDown();
    606767}
    607768
     769void ScriptInterface::Tick()
     770{
     771    js::NotifyAnimationActivity(m->m_glob);
     772}
     773
    608774void ScriptInterface::SetCallbackData(void* pCBData)
    609775{
    610776    m_CxPrivate.pCBData = pCBData;
     
    640806        }
    641807    }
    642808    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))
    644810        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))
    646812        m->m_ScriptValCache[CACHE_VECTOR3DPROTO] = CScriptValRooted(m->m_cx, proto);
    647813    return true;
    648814}
    649815
     816
    650817bool ScriptInterface::ReplaceNondeterministicRNG(boost::rand48& rng)
    651818{
    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()))
    654822    {
    655823        JSFunction* random = JS_DefineFunction(m->m_cx, JSVAL_TO_OBJECT(math), "random", Math_random, 0,
    656824            JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT);
    657825        if (random)
    658826        {
    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;
    662829        }
    663830    }
    664831
     
    668835
    669836void ScriptInterface::Register(const char* name, JSNative fptr, size_t nargs)
    670837{
    671     m->Register(name, fptr, (uintN)nargs);
     838    m->Register(name, fptr, (uint)nargs);
    672839}
    673840
    674841JSContext* ScriptInterface::GetContext() const
     
    686853    return m->m_runtime;
    687854}
    688855
    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 }
    695856
    696 
    697 jsval ScriptInterface::CallConstructor(jsval ctor, jsval arg)
     857jsval ScriptInterface::CallConstructor(jsval ctor, int argc, jsval argv)
    698858{
    699     if (!JSVAL_IS_OBJECT(ctor))
     859    JSAutoRequest rq(m->m_cx);
     860    if (JSVAL_IS_PRIMITIVE(ctor))
    700861    {
    701862        LOGERROR(L"CallConstructor: ctor is not an object");
    702863        return JSVAL_VOID;
    703864    }
    704865
    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));
    706873}
    707874
    708875jsval ScriptInterface::NewObjectFromConstructor(jsval ctor)
    709876{
     877    JSAutoRequest rq(m->m_cx);
    710878    // Get the constructor's prototype
    711879    // (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()))
    714882    {
    715883        LOGERROR(L"NewObjectFromConstructor: can't get prototype");
    716884        return JSVAL_VOID;
    717885    }
    718886
    719     if (!JSVAL_IS_OBJECT(protoVal))
     887    if (JSVAL_IS_PRIMITIVE(protoVal.get()))
    720888    {
    721889        LOGERROR(L"NewObjectFromConstructor: prototype is not an object");
    722890        return JSVAL_VOID;
    723891    }
    724892
    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));
    727895    // TODO: rooting?
    728896    if (!proto || !parent)
    729897    {
     
    743911
    744912void ScriptInterface::DefineCustomObjectType(JSClass *clasp, JSNative constructor, uint minArgs, JSPropertySpec *ps, JSFunctionSpec *fs, JSPropertySpec *static_ps, JSFunctionSpec *static_fs)
    745913{
     914    JSAutoRequest rq(m->m_cx);
    746915    std::string typeName = clasp->name;
    747916
    748917    if (m_CustomObjectTypes.find(typeName) != m_CustomObjectTypes.end())
     
    790959
    791960bool ScriptInterface::CallFunction_(jsval val, const char* name, size_t argc, jsval* argv, jsval& ret)
    792961{
     962    JSAutoRequest rq(m->m_cx);
    793963    JSObject* obj;
    794964    if (!JS_ValueToObject(m->m_cx, val, &obj) || obj == NULL)
    795965        return false;
     
    798968    // when calling an undefined value
    799969    JSBool found;
    800970    if (!JS_HasProperty(m->m_cx, obj, name, &found) || !found)
    801         return false;
     971        return JS_FALSE;
    802972
    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);
    804974
    805     return ok ? true : false;
     975    return ok ? JS_TRUE : JS_FALSE;
    806976}
    807977
    808978jsval ScriptInterface::GetGlobalObject()
    809979{
    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));
    811982}
    812983
    813984JSClass* ScriptInterface::GetGlobalClass()
     
    817988
    818989bool ScriptInterface::SetGlobal_(const char* name, jsval value, bool replace)
    819990{
     991    JSAutoRequest rq(m->m_cx);
    820992    if (!replace)
    821993    {
    822994        JSBool found;
    823995        if (!JS_HasProperty(m->m_cx, m->m_glob, name, &found))
    824             return false;
     996            return JS_FALSE;
    825997        if (found)
    826998        {
    827999            JS_ReportError(m->m_cx, "SetGlobal \"%s\" called multiple times", name);
    828             return false;
     1000            return JS_FALSE;
    8291001        }
    8301002    }
    8311003
    832     JSBool ok = JS_DefineProperty(m->m_cx, m->m_glob, name, value, NULL, NULL, JSPROP_ENUMERATE | JSPROP_READONLY
    833             | 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;
    8351007}
    8361008
    8371009bool ScriptInterface::SetProperty_(jsval obj, const char* name, jsval value, bool constant, bool enumerate)
    8381010{
    839     uintN attrs = 0;
     1011    JSAutoRequest rq(m->m_cx);
     1012    uint attrs = 0;
    8401013    if (constant)
    8411014        attrs |= JSPROP_READONLY | JSPROP_PERMANENT;
    8421015    if (enumerate)
    8431016        attrs |= JSPROP_ENUMERATE;
    8441017
    845     if (! JSVAL_IS_OBJECT(obj))
     1018    if (JSVAL_IS_PRIMITIVE(obj))
    8461019        return false;
    8471020    JSObject* object = JSVAL_TO_OBJECT(obj);
    8481021
     
    8531026
    8541027bool ScriptInterface::SetProperty_(jsval obj, const wchar_t* name, jsval value, bool constant, bool enumerate)
    8551028{
    856     uintN attrs = 0;
     1029    JSAutoRequest rq(m->m_cx);
     1030    uint attrs = 0;
    8571031    if (constant)
    8581032        attrs |= JSPROP_READONLY | JSPROP_PERMANENT;
    8591033    if (enumerate)
    8601034        attrs |= JSPROP_ENUMERATE;
    8611035
    862     if (! JSVAL_IS_OBJECT(obj))
     1036    if ( JSVAL_IS_PRIMITIVE(obj))
    8631037        return false;
    8641038    JSObject* object = JSVAL_TO_OBJECT(obj);
    8651039
     
    8711045
    8721046bool ScriptInterface::SetPropertyInt_(jsval obj, int name, jsval value, bool constant, bool enumerate)
    8731047{
    874     uintN attrs = 0;
     1048    JSAutoRequest rq(m->m_cx);
     1049    uint attrs = 0;
    8751050    if (constant)
    8761051        attrs |= JSPROP_READONLY | JSPROP_PERMANENT;
    8771052    if (enumerate)
    8781053        attrs |= JSPROP_ENUMERATE;
    8791054
    880     if (! JSVAL_IS_OBJECT(obj))
     1055    if ( JSVAL_IS_PRIMITIVE(obj))
    8811056        return false;
    8821057    JSObject* object = JSVAL_TO_OBJECT(obj);
    8831058
     
    8861061    return true;
    8871062}
    8881063
    889 bool ScriptInterface::GetProperty_(jsval obj, const char* name, jsval& out)
     1064bool ScriptInterface::GetProperty_(jsval obj, const char* name, JS::MutableHandleValue out)
    8901065{
    891     if (! JSVAL_IS_OBJECT(obj))
     1066    JSAutoRequest rq(m->m_cx);
     1067    if ( JSVAL_IS_PRIMITIVE(obj))
    8921068        return false;
    8931069    JSObject* object = JSVAL_TO_OBJECT(obj);
    8941070
    895     if (!JS_GetProperty(m->m_cx, object, name, &out))
     1071    if (!JS_GetProperty(m->m_cx, object, name, out.address()))
    8961072        return false;
    8971073    return true;
    8981074}
    8991075
    900 bool ScriptInterface::GetPropertyInt_(jsval obj, int name, jsval& out)
     1076bool ScriptInterface::GetPropertyInt_(jsval obj, int name, JS::MutableHandleValue out)
    9011077{
    902     if (! JSVAL_IS_OBJECT(obj))
     1078    JSAutoRequest rq(m->m_cx);
     1079    if ( JSVAL_IS_PRIMITIVE(obj))
    9031080        return false;
    9041081    JSObject* object = JSVAL_TO_OBJECT(obj);
    9051082
    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()))
    9071084        return false;
    9081085    return true;
    9091086}
    9101087
    9111088bool ScriptInterface::HasProperty(jsval obj, const char* name)
    9121089{
    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;
    9151094    JSObject* object = JSVAL_TO_OBJECT(obj);
    9161095
    9171096    JSBool found;
    9181097    if (!JS_HasProperty(m->m_cx, object, name, &found))
    919         return false;
    920     return (found != JS_FALSE);
     1098        return JS_FALSE;
     1099    return found;
    9211100}
    9221101
    923 bool ScriptInterface::EnumeratePropertyNamesWithPrefix(jsval obj, const char* prefix, std::vector<std::string>& out)
     1102bool ScriptInterface::EnumeratePropertyNamesWithPrefix(JS::HandleObject obj, const char* prefix, std::vector<std::string>& out)
    9241103{
    925     utf16string prefix16 (prefix, prefix+strlen(prefix));
     1104    JSAutoRequest rq(m->m_cx);
     1105    if (obj.get() == 0x0)
     1106        return true;
    9261107
    927     if (! JSVAL_IS_OBJECT(obj))
    928         return false; // TODO: log error messages
     1108//  if ( obj.get().isPrimitive() )
     1109//      return false; // TODO: log error messages
    9291110
    930     JSObject* it = JS_NewPropertyIterator(m->m_cx, JSVAL_TO_OBJECT(obj));
     1111    JSObject* it = JS_NewPropertyIterator(m->m_cx, obj.get());
    9311112    if (!it)
    9321113        return false;
    9331114
     
    9431124            continue; // ignore integer properties
    9441125
    9451126        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
    9501141    }
    9511142
    9521143    // Recurse up the prototype chain
    953     JSObject* 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()))
    9551146    {
    956         if (! EnumeratePropertyNamesWithPrefix(OBJECT_TO_JSVAL(prototype), prefix, out))
     1147        if (! EnumeratePropertyNamesWithPrefix(prototype, prefix, out))
    9571148            return false;
    9581149    }
    9591150
    9601151    return true;
    9611152}
    9621153
    963 bool ScriptInterface::SetPrototype(jsval obj, jsval proto)
     1154bool ScriptInterface::SetPrototype(JS::HandleObject obj, JS::HandleObject proto)
    9641155{
    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);
    9681160}
    9691161
    9701162bool ScriptInterface::FreezeObject(jsval obj, bool deep)
    9711163{
    972     if (!JSVAL_IS_OBJECT(obj))
     1164    JSAutoRequest rq(m->m_cx);
     1165    if (JSVAL_IS_PRIMITIVE(obj))
    9731166        return false;
    9741167
    9751168    if (deep)
     
    9801173
    9811174bool ScriptInterface::LoadScript(const VfsPath& filename, const std::string& code)
    9821175{
    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;
    9881179
    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    );
    9931185    if (!func)
    9941186        return false;
    9951187
    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());
    9981190
    9991191    return ok ? true : false;
    10001192}
    10011193
    10021194bool ScriptInterface::LoadGlobalScript(const VfsPath& filename, const std::wstring& code)
    10031195{
    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;
    10091199
    10101200    jsval rval;
    1011     JSBool ok = JS_EvaluateUCScript(m->m_cx, m->m_glob,
    1012             reinterpret_cast<const jschar*> (codeUtf16.c_str()), (uintN)(codeUtf16.length()),
     1201    bool ok = JS_EvaluateUCScript(m->m_cx, m->m_glob,
     1202            reinterpret_cast<const jschar*> (codeUtf16.c_str()), (uint)(codeUtf16.length()),
    10131203            utf8_from_wstring(filename.string()).c_str(), lineNo, &rval);
    10141204
    1015     return ok ? true : false;
     1205    return ok;
    10161206}
    10171207
    10181208bool ScriptInterface::LoadGlobalScriptFile(const VfsPath& path)
    10191209{
     1210    JSAutoRequest rq(m->m_cx);
    10201211    if (!VfsFileExists(path))
    10211212    {
    10221213        LOGERROR(L"File '%ls' does not exist", path.string().c_str());
     
    10351226
    10361227    std::wstring code = wstring_from_utf8(file.DecodeUTF8()); // assume it's UTF-8
    10371228
    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;
    10431231
    10441232    jsval rval;
    1045     JSBool ok = JS_EvaluateUCScript(m->m_cx, m->m_glob,
    1046             reinterpret_cast<const jschar*> (codeUtf16.c_str()), (uintN)(codeUtf16.length()),
     1233    bool ok = JS_EvaluateUCScript(m->m_cx, m->m_glob,
     1234            reinterpret_cast<const jschar*> (codeUtf16.c_str()), (uint)(codeUtf16.length()),
    10471235            utf8_from_wstring(path.string()).c_str(), lineNo, &rval);
    10481236
    1049     return ok ? true : false;
     1237    return ok;
    10501238}
    10511239
    10521240bool ScriptInterface::Eval(const char* code)
     
    10571245
    10581246bool ScriptInterface::Eval_(const char* code, jsval& rval)
    10591247{
     1248    JSAutoRequest rq(m->m_cx);
    10601249    utf16string codeUtf16(code, code+strlen(code));
    10611250
    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;
    10641253}
    10651254
    10661255bool ScriptInterface::Eval_(const wchar_t* code, jsval& rval)
    10671256{
     1257    JSAutoRequest rq(m->m_cx);
    10681258    utf16string codeUtf16(code, code+wcslen(code));
    10691259
    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;
    10721262}
    10731263
    10741264CScriptValRooted ScriptInterface::ParseJSON(const std::string& string_utf8)
    10751265{
     1266    JSAutoRequest rq(m->m_cx);
    10761267    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);
    10991271    return CScriptValRooted(m->m_cx, vp);
    11001272}
    11011273
     
    11241296
    11251297struct Stringifier
    11261298{
    1127     static JSBool callback(const jschar* buf, uint32 len, void* data)
     1299    static JSBool callback(const jschar* buf, uint32_t len, void* data)
    11281300    {
    11291301        utf16string str(buf, buf+len);
    11301302        std::wstring strw(str.begin(), str.end());
     
    11391311
    11401312struct StringifierW
    11411313{
    1142     static JSBool callback(const jschar* buf, uint32 len, void* data)
     1314    static JSBool callback(const jschar* buf, uint32_t len, void* data)
    11431315    {
    11441316        utf16string str(buf, buf+len);
    11451317        static_cast<StringifierW*>(data)->stream << std::wstring(str.begin(), str.end());
     
    11511323
    11521324std::string ScriptInterface::StringifyJSON(jsval obj, bool indent)
    11531325{
     1326    JSAutoRequest rq(m->m_cx);
    11541327    Stringifier str;
    11551328    if (!JS_Stringify(m->m_cx, &obj, NULL, indent ? INT_TO_JSVAL(2) : JSVAL_VOID, &Stringifier::callback, &str))
    11561329    {
     
    11661339
    11671340std::wstring ScriptInterface::ToString(jsval obj, bool pretty)
    11681341{
     1342    JSAutoRequest rq(m->m_cx);
    11691343    if (JSVAL_IS_VOID(obj))
    11701344        return L"(void 0)";
    11711345
     
    11781352        // Temporary disable the error reporter, so we don't print complaints about cyclic values
    11791353        JSErrorReporter er = JS_SetErrorReporter(m->m_cx, NULL);
    11801354
    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);
    11821356
    11831357        // Restore error reporter
    11841358        JS_SetErrorReporter(m->m_cx, er);
     
    12001374
    12011375void ScriptInterface::ReportError(const char* msg)
    12021376{
     1377    JSAutoRequest rq(m->m_cx);
    12031378    // JS_ReportError by itself doesn't seem to set a JS-style exception, and so
    12041379    // script callers will be unable to catch anything. So use JS_SetPendingException
    12051380    // to make sure there really is a script-level exception. But just set it to undefined
     
    12131388
    12141389bool ScriptInterface::IsExceptionPending(JSContext* cx)
    12151390{
     1391    JSAutoRequest rq(cx);
    12161392    return JS_IsExceptionPending(cx) ? true : false;
    12171393}
    12181394
    1219 JSClass* ScriptInterface::GetClass(JSContext* cx, JSObject* obj)
     1395JSClass* ScriptInterface::GetClass(JSObject* obj)
    12201396{
    1221     UNUSED2(cx); // unused if not JS_THREADSAFE
    1222 
    1223     return JS_GET_CLASS(cx, obj);
     1397    return JS_GetClass(obj);
    12241398}
    12251399
    1226 void* ScriptInterface::GetPrivate(JSContext* cx, JSObject* obj)
     1400void* ScriptInterface::GetPrivate(JSObject* obj)
    12271401{
    12281402    // TODO: use JS_GetInstancePrivate
    1229     return JS_GetPrivate(cx, obj);
     1403    return JS_GetPrivate(obj);
    12301404}
    12311405
    12321406void ScriptInterface::DumpHeap()
    12331407{
    12341408#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);
    12361410#endif
    12371411    fprintf(stderr, "# Bytes allocated: %u\n", JS_GetGCParameter(GetJSRuntime(), JSGC_BYTES));
    1238     JS_GC(m->m_cx);
     1412    JS_GC(GetJSRuntime());
    12391413    fprintf(stderr, "# Bytes allocated after GC: %u\n", JS_GetGCParameter(GetJSRuntime(), JSGC_BYTES));
    12401414}
    12411415
     1416void ScriptInterface::MaybeIncrementalRuntimeGC()
     1417{
     1418    m->m_runtime->MaybeIncrementalGC();
     1419}
     1420
    12421421void ScriptInterface::MaybeGC()
    12431422{
    12441423    JS_MaybeGC(m->m_cx);
    12451424}
    12461425
     1426void ScriptInterface::ForceGC()
     1427{
     1428    PROFILE2("JS_GC");
     1429    JS_GC(this->GetJSRuntime());
     1430}
     1431
    12471432class ValueCloner
    12481433{
    12491434public:
    12501435    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())
    12521437    {
    12531438    }
    12541439
     
    12621447        if (it != m_Mapping.end())
    12631448            return it->second;
    12641449
    1265         m_RooterFrom.Push(val); // root it so our mapping doesn't get invalidated
     1450        m_RooterFrom.append(val); // root it so our mapping doesn't get invalidated
    12661451
    12671452        return Clone(val);
    12681453    }
     
    12741459    // Clone a new value (and root it and add it to the mapping)
    12751460    jsval Clone(jsval val)
    12761461    {
     1462        JSAutoRequest rq(cxFrom);
    12771463        if (JSVAL_IS_DOUBLE(val))
    12781464        {
    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);
    12821468            return rval;
    12831469        }
    12841470
     
    12871473            size_t len;
    12881474            const jschar* chars = JS_GetStringCharsAndLength(cxFrom, JSVAL_TO_STRING(val), &len);
    12891475            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            }
    12961485        }
    12971486
    1298         ENSURE(JSVAL_IS_OBJECT(val));
     1487        ENSURE(!JSVAL_IS_PRIMITIVE(val));
    12991488
    13001489        JSObject* newObj;
    13011490        if (JS_IsArrayObject(cxFrom, JSVAL_TO_OBJECT(val)))
    13021491        {
    1303             jsuint length;
     1492            uint length;
    13041493            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            }   
    13061498            CLONE_REQUIRE(newObj, L"JS_NewArrayObject");
    13071499        }
    13081500        else
    13091501        {
    1310             newObj = JS_NewObject(cxTo, NULL, NULL, NULL);
     1502            {
     1503                JSAutoRequest rq(cxTo);
     1504                newObj = JS_NewObject(cxTo, NULL, NULL, NULL);
     1505            }
    13111506            CLONE_REQUIRE(newObj, L"JS_NewObject");
    13121507        }
    13131508
    13141509        m_Mapping[JSVAL_TO_GCTHING(val)] = OBJECT_TO_JSVAL(newObj);
    1315         m_RooterTo.Push(newObj);
     1510        m_RooterTo.append(OBJECT_TO_JSVAL(newObj));
    13161511
    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);
    13191517
    1320         AutoGCRooter idaRooter(scriptInterfaceFrom);
    1321         idaRooter.Push(ida.get());
    1322 
    13231518        for (size_t i = 0; i < ida.length(); ++i)
    13241519        {
    13251520            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));
    13301526
    13311527            if (JSVAL_IS_INT(idval))
    13321528            {
    13331529                // 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                        }
    13361533            else if (JSVAL_IS_STRING(idval))
    13371534            {
    13381535                // string jsids are runtime-specific, so we need to copy the string content
     
    13411538                size_t len;
    13421539                const jschar* chars = JS_GetStringCharsAndLength(cxFrom, idstr, &len);
    13431540                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                }
    13451545            }
    13461546            else
    13471547            {
     
    13561556    JSContext* cxFrom;
    13571557    JSContext* cxTo;
    13581558    std::map<void*, jsval> m_Mapping;
    1359     AutoGCRooter m_RooterFrom;
    1360     AutoGCRooter m_RooterTo;
     1559    JS::AutoValueVector m_RooterFrom;
     1560    JS::AutoValueVector m_RooterTo;
    13611561};
    13621562
    13631563jsval ScriptInterface::CloneValueFromOtherContext(ScriptInterface& otherContext, jsval val)
     
    13691569}
    13701570
    13711571ScriptInterface::StructuredClone::StructuredClone() :
    1372     m_Context(NULL), m_Data(NULL), m_Size(0)
     1572    m_Data(NULL), m_Size(0)
    13731573{
    13741574}
    13751575
    13761576ScriptInterface::StructuredClone::~StructuredClone()
    13771577{
    13781578    if (m_Data)
    1379         JS_free(m_Context, m_Data);
     1579        JS_ClearStructuredClone(m_Data, m_Size);
    13801580}
    13811581
    13821582shared_ptr<ScriptInterface::StructuredClone> ScriptInterface::WriteStructuredClone(jsval v)
    13831583{
    1384     uint64* data = NULL;
     1584    JSAutoRequest rq(m->m_cx);
     1585    uint64_t* data = NULL;
    13851586    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))
    13871588    {
    13881589        debug_warn(L"Writing a structured clone with JS_WriteStructuredClone failed!");
    13891590        return shared_ptr<StructuredClone>();
    13901591    }
    13911592
    13921593    shared_ptr<StructuredClone> ret (new StructuredClone);
    1393     ret->m_Context = m->m_cx;
    13941594    ret->m_Data = data;
    13951595    ret->m_Size = nbytes;
    13961596    return ret;
     
    13981598
    13991599jsval ScriptInterface::ReadStructuredClone(const shared_ptr<ScriptInterface::StructuredClone>& ptr)
    14001600{
     1601    JSAutoRequest rq(m->m_cx);
    14011602    jsval ret = JSVAL_VOID;
    14021603    JS_ReadStructuredClone(m->m_cx, ptr->m_Data, ptr->m_Size, JS_STRUCTURED_CLONE_VERSION, &ret, NULL, NULL);
    14031604    return ret;
  • source/scriptinterface/ScriptInterface.h

     
    2525#include "ScriptTypes.h"
    2626#include "ScriptVal.h"
    2727
    28 #include "js/jsapi.h"
    29 
    3028#include "ps/Errors.h"
    3129ERROR_GROUP(Scripting);
    3230ERROR_TYPE(Scripting, SetupFailed);
     
    5250
    5351#include <boost/random/linear_congruential.hpp>
    5452
    55 class AutoGCRooter;
    56 
    5753// Set the maximum number of function arguments that can be handled
    5854// (This should be as small as possible (for compiler efficiency),
    5955// but as large as necessary for all wrapped functions)
     
    115111        void* pCBData; // meant to be used as the "this" object for callback functions
    116112    } m_CxPrivate;
    117113
     114    void Tick();
    118115    void SetCallbackData(void* pCBData);
    119116    static CxPrivate* GetScriptInterfaceAndCBData(JSContext* cx);
    120117
     
    140137     * Call a constructor function, equivalent to JS "new ctor(arg)".
    141138     * @return The new object; or JSVAL_VOID on failure, and logs an error message
    142139     */
    143     jsval CallConstructor(jsval ctor, jsval arg);
     140    jsval CallConstructor(jsval ctor, int argc, jsval argv);
    144141
    145142    /**
    146143     * Create an object as with CallConstructor except don't actually execute the
     
    255252     */
    256253    bool HasProperty(jsval obj, const char* name);
    257254
    258     bool EnumeratePropertyNamesWithPrefix(jsval obj, const char* prefix, std::vector<std::string>& out);
     255    bool EnumeratePropertyNamesWithPrefix(JS::HandleObject obj, const char* prefix, std::vector<std::string>& out);
    259256
    260     bool SetPrototype(jsval obj, jsval proto);
     257    bool SetPrototype(JS::HandleObject obj, JS::HandleObject proto);
    261258
    262259    bool FreezeObject(jsval obj, bool deep);
    263260
     
    330327     */
    331328    template<typename T> static jsval ToJSVal(JSContext* cx, T const& val);
    332329
    333     AutoGCRooter* ReplaceAutoGCRooter(AutoGCRooter* rooter);
    334 
    335330    /**
    336331     * Dump some memory heap debugging information to stderr.
    337332     */
     
    341336     * 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
    342337     */
    343338    void MaybeGC();
     339   
     340    void MaybeIncrementalRuntimeGC();
     341   
     342    void ForceGC();
    344343
     344    bool MathRandom(double& nbr);
     345
    345346    /**
    346347     * Structured clones are a way to serialize 'simple' JS values into a buffer
    347348     * that can safely be passed between contexts and runtimes and threads.
     
    355356    public:
    356357        StructuredClone();
    357358        ~StructuredClone();
    358         JSContext* m_Context;
    359         uint64* m_Data;
     359        uint64_t* m_Data;
    360360        size_t m_Size;
    361361    };
    362362
     
    371371    bool SetProperty_(jsval obj, const char* name, jsval value, bool readonly, bool enumerate);
    372372    bool SetProperty_(jsval obj, const wchar_t* name, jsval value, bool readonly, bool enumerate);
    373373    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);
    376376    static bool IsExceptionPending(JSContext* cx);
    377     static JSClass* GetClass(JSContext* cx, JSObject* obj);
    378     static void* GetPrivate(JSContext* cx, JSObject* obj);
     377    static JSClass* GetClass(JSObject* obj);
     378    static void* GetPrivate(JSObject* obj);
    379379
    380380    class CustomType
    381381    {
     
    387387    void Register(const char* name, JSNative fptr, size_t nargs);
    388388    std::auto_ptr<ScriptInterface_impl> m;
    389389   
     390    boost::rand48* m_rng;
    390391    std::map<std::string, CustomType> m_CustomObjectTypes;
    391392
    392393// The nasty macro/template bits are split into a separate file so you don't have to look at them
     
    531532template<typename T>
    532533bool ScriptInterface::GetProperty(jsval obj, const char* name, T& out)
    533534{
    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))
    536539        return false;
    537     return FromJSVal(GetContext(), val, out);
     540    return FromJSVal(cx, val, out);
    538541}
    539542
    540543template<typename T>
    541544bool ScriptInterface::GetPropertyInt(jsval obj, int name, T& out)
    542545{
    543     jsval val;
    544     if (! GetPropertyInt_(obj, name, val))
     546    JSAutoRequest rq(GetContext());
     547    JS::RootedValue val(GetContext());
     548    if (! GetPropertyInt_(obj, name, &val))
    545549        return false;
    546550    return FromJSVal(GetContext(), val, out);
    547551}
  • source/scriptinterface/ScriptStats.cpp

     
    2121
    2222#include "scriptinterface/ScriptInterface.h"
    2323
    24 #include "js/jsapi.h"
    25 
    2624CScriptStatsTable* g_ScriptStatsTable;
    2725
    2826enum
  • source/scriptinterface/ScriptTypes.h

     
    3333// the ones that are needed and this avoids conflicting definitions
    3434# define JS_SYS_TYPES_H_DEFINES_EXACT_SIZE_TYPES
    3535
     36
    3637#else // If not Windows, then Unix:
    3738
    3839# define XP_UNIX
    3940
    40 // In DEBUG mode, jsval defaults to struct types. Normally we build separate
    41 // debug/release mode versions of the library, but when using --with-system-mozjs185
    42 // it's always a release mode library, so we have to disable struct types for
    43 // ABI compatibility
    44 # if defined(DEBUG) && defined(WITH_SYSTEM_MOZJS185)
    45 #  define JS_NO_JSVAL_JSID_STRUCT_TYPES
    46 # endif
    47 
    4841#endif
    4942// (we don't support XP_OS2 or XP_BEOS)
    5043
    5144
    5245// Guess whether the library was compiled with the release-mode or debug-mode ABI
    5346// (for JS_DumpHeap etc)
    54 #if defined(DEBUG) && !defined(WITH_SYSTEM_MOZJS185)
     47#if defined(DEBUG) && !defined(WITH_SYSTEM_MOZJS24)
    5548# define MOZJS_DEBUG_ABI 1
    5649#else
    5750# define MOZJS_DEBUG_ABI 0
    5851#endif
    5952
    60 
    61 // SpiderMonkey wants the DEBUG flag
    62 #ifndef NDEBUG
    63 # ifndef DEBUG
    64 #  define DEBUG
    65 # endif
    66 #endif
    67 
    6853// 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
    7060# pragma GCC diagnostic ignored "-Wunused-parameter"
    7161# 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
    7267#endif
    7368#if MSC_VERSION
    7469# pragma warning(push)
     
    7671# pragma warning(disable:4100) // "unreferenced formal parameter"
    7772#endif
    7873
    79 #include "js/jsapi.h"
     74#include "jspubtd.h"
     75#include "jsapi.h"
    8076
     77
    8178#if MSC_VERSION
    8279# pragma warning(pop)
    8380#endif
    8481#if GCC_VERSION >= 402
    8582# pragma GCC diagnostic warning "-Wunused-parameter"
    8683# 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"
    8790#endif
    8891
    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 #endif
     92//#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
    9598
    9699class ScriptInterface;
    97100class CScriptVal;
  • source/scriptinterface/ScriptVal.cpp

     
    1717
    1818#include "precompiled.h"
    1919
     20#include "ScriptInterface.h"
    2021#include "ScriptVal.h"
    2122
    22 #include "js/jsapi.h"
    2323
    2424struct Unrooter
    2525{
    2626    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    }
    2832    JSContext* cx;
    2933};
    3034
    3135CScriptValRooted::CScriptValRooted(JSContext* cx, jsval val)
    3236{
     37    JSAutoRequest rq(cx);
    3338    jsval* p = new jsval(val);
    3439    JS_AddNamedValueRoot(cx, p, "CScriptValRooted");
    3540    m_Val = boost::shared_ptr<jsval>(p, Unrooter(cx));
     
    3742
    3843CScriptValRooted::CScriptValRooted(JSContext* cx, CScriptVal val)
    3944{
     45    JSAutoRequest rq(cx);
    4046    jsval* p = new jsval(val.get());
    4147    JS_AddNamedValueRoot(cx, p, "CScriptValRooted");
    4248    m_Val = boost::shared_ptr<jsval>(p, Unrooter(cx));
     
    6470{
    6571    return !m_Val;
    6672}
    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() const
    80 {
    81     return m_IdArray;
    82 }
    83 
    84 size_t AutoJSIdArray::length() const
    85 {
    86     if (!m_IdArray)
    87         return 0;
    88     return m_IdArray->length;
    89 }
    90 
    91 jsid AutoJSIdArray::operator[](size_t i) const
    92 {
    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

     
    2323#include "maths/MathUtil.h"
    2424#include "ps/CLogger.h"
    2525
    26 #include "js/jsapi.h"
     26#include "jsapi.h"
    2727
    2828class TestScriptConversions : public CxxTest::TestSuite
    2929{
     
    3838        // We want to convert values to strings, but can't just call toSource() on them
    3939        // since they might not be objects. So just use uneval.
    4040        std::string source;
    41         TS_ASSERT(script.CallFunction(OBJECT_TO_JSVAL(JS_GetGlobalObject(cx)), "uneval", CScriptVal(v1), source));
     41        TS_ASSERT(script.CallFunction(OBJECT_TO_JSVAL(JS_GetGlobalForScopeChain(cx)), "uneval", CScriptVal(v1), source));
    4242
    4343        TS_ASSERT_STR_EQUALS(source, expected);
    4444    }
     
    5252        jsval v1 = ScriptInterface::ToJSVal(cx, value);
    5353
    5454        std::string source;
    55         TS_ASSERT(script.CallFunction(OBJECT_TO_JSVAL(JS_GetGlobalObject(cx)), "uneval", CScriptVal(v1), source));
     55        TS_ASSERT(script.CallFunction(OBJECT_TO_JSVAL(JS_GetGlobalForScopeChain(cx)), "uneval", CScriptVal(v1), source));
    5656
    5757        if (expected)
    5858            TS_ASSERT_STR_EQUALS(source, expected);
  • source/scriptinterface/tests/test_ScriptVal.h

     
    2020#include "scriptinterface/ScriptInterface.h"
    2121#include "scriptinterface/ScriptVal.h"
    2222
    23 #include "js/jsapi.h"
     23#include "jsapi.h"
    2424
    2525class TestScriptVal : public CxxTest::TestSuite
    2626{
     
    3535
    3636        CScriptValRooted root(cx, OBJECT_TO_JSVAL(obj));
    3737
    38         JS_GC(cx);
     38        JS_GC(script.GetRuntime());
    3939
    4040        jsval val = INT_TO_JSVAL(123);
    4141        TS_ASSERT(JS_SetProperty(cx, obj, "test", &val));
    4242
    43         JS_GC(cx);
     43        JS_GC(script.GetRuntime());
    4444
    4545        jsval rval;
    4646        TS_ASSERT(JS_GetProperty(cx, obj, "test", &rval));
  • source/simulation2/Simulation2.cpp

     
    1919
    2020#include "Simulation2.h"
    2121
     22#include "scriptinterface/ScriptInterface.h"
     23
    2224#include "simulation2/MessageTypes.h"
    2325#include "simulation2/system/ComponentManager.h"
    2426#include "simulation2/system/ParamNode.h"
     
    155157    }
    156158
    157159    int ProgressiveLoad();
     160
     161    void Tick();
    158162    void Update(int turnLength, const std::vector<SimulationCommand>& commands);
    159163    static void UpdateComponents(CSimContext& simContext, fixed turnLengthFixed, const std::vector<SimulationCommand>& commands);
    160164    void Interpolate(float simFrameLength, float frameOffset, float realFrameLength);
     
    336340    debug_warn(L"Serialization test failure");
    337341}
    338342
     343void CSimulation2Impl::Tick()
     344{
     345    m_ComponentManager.Tick();
     346}
     347
    339348void CSimulation2Impl::Update(int turnLength, const std::vector<SimulationCommand>& commands)
    340349{
    341350    PROFILE3("sim update");
     
    451460    // Run the GC occasionally
    452461    // (TODO: we ought to schedule this for a frame where we're not
    453462    // running the sim update, to spread the load)
    454     if (m_TurnNumber % 10 == 0)
    455         m_ComponentManager.GetScriptInterface().MaybeGC();
     463    if (m_TurnNumber % 1 == 0)
     464        m_ComponentManager.GetScriptInterface().MaybeIncrementalRuntimeGC();
    456465
    457466    if (m_EnableOOSLog)
    458467        DumpState();
     
    637646    return m->m_ComponentManager.GetEntitiesWithInterfaceUnordered(iid);
    638647}
    639648
     649void CSimulation2::Tick()
     650{
     651    m->Tick();
     652}
     653
    640654const CSimContext& CSimulation2::GetSimContext() const
    641655{
    642656    return m->m_SimContext;
  • source/simulation2/Simulation2.h

     
    5353    ~CSimulation2();
    5454
    5555    void EnableOOSLog();
     56    void Tick();
    5657    void EnableSerializationTest();
    5758
    5859    /**
  • source/simulation2/components/CCmpAIManager.cpp

     
    152152                ENSURE(m_Worker.m_HasLoadedEntityTemplates);
    153153                m_ScriptInterface->SetProperty(settings.get(), "templates", m_Worker.m_EntityTemplates, false);
    154154
    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));
    156158            }
    157159            else
    158160            {
     
    209211    };
    210212
    211213    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)),
    218215        m_TurnNum(0),
    219216        m_CommandsComputed(true),
    220217        m_HasLoadedEntityTemplates(false),
     
    305302    static void ForceGC(ScriptInterface::CxPrivate* pCxPrivate)
    306303    {
    307304        PROFILE3("AI compute GC");
    308         JS_GC(pCxPrivate->pScriptInterface->GetContext());
     305        JS_GC(pCxPrivate->pScriptInterface->GetJSRuntime());
    309306    }
    310307   
    311308    /**
     
    408405            m_ScriptInterface->Eval("({})", fakeTech);
    409406            m_ScriptInterface->SetProperty(settings.get(), "techTemplates", fakeTech, false);
    410407        }
    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)));
    412412   
    413413       
    414414        if (m_SharedAIObj.undefined())
     
    430430        if (!m_HasSharedComponent)
    431431            m_HasSharedComponent = ai->m_UseSharedComponent;
    432432
    433         m_ScriptInterface->MaybeGC();
    434 
    435433        m_Players.push_back(ai);
    436434
    437435        return true;
     
    453451            m_ScriptInterface->SetProperty(state.get(), "territoryMap", m_TerritoryMapVal, true);
    454452
    455453            m_ScriptInterface->CallFunctionVoid(m_SharedAIObj.get(), "init", state);
    456             m_ScriptInterface->MaybeGC();
    457454           
    458455            for (size_t i = 0; i < m_Players.size(); ++i)
    459456            {
     
    706703    }
    707704
    708705    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    {           
    723707        // Deserialize the game state, to pass to the AI's HandleMessage
    724708        CScriptVal state;
    725709        {
     
    753737            else
    754738                m_Players[i]->Run(state, m_Players[i]->m_Player);
    755739        }
    756 
    757         // Run GC if we are about to overflow
    758         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 clearer
    767         // 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         }*/
    773740    }
    774741
    775742    shared_ptr<ScriptRuntime> m_ScriptRuntime;
  • source/simulation2/components/ICmpFootprint.cpp

     
    3838
    3939    if (shape == CIRCLE)
    4040    {
    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());
    4747    }
    4848    else
    4949    {
    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());
    5858    }
    5959
    6060    return OBJECT_TO_JSVAL(obj);
  • source/simulation2/scripting/EngineScriptConversions.cpp

     
    3434
    3535template<> jsval ScriptInterface::ToJSVal<IComponent*>(JSContext* cx, IComponent* const& val)
    3636{
     37    JSAutoRequest rq(cx);
    3738    if (val == NULL)
    3839        return JSVAL_NULL;
    3940
     
    5859        LOGERROR(L"Failed to construct IComponent script object");
    5960        return JSVAL_VOID;
    6061    }
    61     JS_SetPrivate(cx, obj, static_cast<void*>(val));
     62    JS_SetPrivate(obj, static_cast<void*>(val));
    6263
    6364    return OBJECT_TO_JSVAL(obj);
    6465}
    6566
    6667template<> jsval ScriptInterface::ToJSVal<CParamNode>(JSContext* cx, CParamNode const& val)
    6768{
     69    JSAutoRequest rq(cx);
    6870    jsval rval = val.ToJSVal(cx, true);
    6971
    7072    // Prevent modifications to the object, so that it's safe to share between
    7173    // components and to reconstruct on deserialization
    72     if (JSVAL_IS_OBJECT(rval))
     74    if (!JSVAL_IS_PRIMITIVE(rval))
    7375        JS_DeepFreezeObject(cx, JSVAL_TO_OBJECT(rval));
    7476
    7577    return rval;
     
    8587
    8688template<> bool ScriptInterface::FromJSVal<CColor>(JSContext* cx, jsval v, CColor& out)
    8789{
    88     if (!JSVAL_IS_OBJECT(v))
     90    if (JSVAL_IS_PRIMITIVE(v))
    8991        FAIL("jsval not an object");
    9092
     93    JSAutoRequest rq(cx);
    9194    JSObject* obj = JSVAL_TO_OBJECT(v);
    9295
    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))
    95101        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))
    97103        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))
    99105        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))
    101107        FAIL("Failed to get property CColor.a");
    102108    // TODO: this probably has GC bugs if a getter returns an unrooted value
    103109
     
    106112
    107113template<> jsval ScriptInterface::ToJSVal<CColor>(JSContext* cx, CColor const& val)
    108114{
     115    JSAutoRequest rq(cx);
    109116    JSObject* obj = JS_NewObject(cx, NULL, NULL, NULL);
    110117    if (!obj)
    111118        return JSVAL_VOID;
    112119
    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));
    117124
    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());
    122129
    123130    return OBJECT_TO_JSVAL(obj);
    124131}
    125132
    126133template<> bool ScriptInterface::FromJSVal<fixed>(JSContext* cx, jsval v, fixed& out)
    127134{
    128     jsdouble ret;
     135    JSAutoRequest rq(cx);
     136    double ret;
    129137    if (!JS_ValueToNumber(cx, v, &ret))
    130138        return false;
    131139    out = fixed::FromDouble(ret);
     
    134142    return true;
    135143}
    136144
    137 template<> jsval ScriptInterface::ToJSVal<fixed>(JSContext* cx, const fixed& val)
     145template<> jsval ScriptInterface::ToJSVal<fixed>(JSContext* UNUSED(cx), const fixed& val)
    138146{
    139     jsval rval = JSVAL_VOID;
    140     JS_NewNumberValue(cx, val.ToDouble(), &rval); // ignore return value
     147    jsval rval = JS_NumberValue(val.ToDouble());
    141148    return rval;
    142149}
    143150
    144151template<> bool ScriptInterface::FromJSVal<CFixedVector3D>(JSContext* cx, jsval v, CFixedVector3D& out)
    145152{
    146     if (!JSVAL_IS_OBJECT(v))
     153    if (JSVAL_IS_PRIMITIVE(v))
    147154        return false; // TODO: report type error
     155
     156    JSAutoRequest rq(cx);
    148157    JSObject* obj = JSVAL_TO_OBJECT(v);
    149158
    150     jsval p;
     159    JS::RootedValue p(cx);
    151160
    152     if (!JS_GetProperty(cx, obj, "x", &p)) return false; // TODO: report type errors
     161    if (!JS_GetProperty(cx, obj, "x", p.address())) return false; // TODO: report type errors
    153162    if (!FromJSVal(cx, p, out.X)) return false;
    154163
    155     if (!JS_GetProperty(cx, obj, "y", &p)) return false;
     164    if (!JS_GetProperty(cx, obj, "y", p.address())) return false;
    156165    if (!FromJSVal(cx, p, out.Y)) return false;
    157166
    158     if (!JS_GetProperty(cx, obj, "z", &p)) return false;
     167    if (!JS_GetProperty(cx, obj, "z", p.address())) return false;
    159168    if (!FromJSVal(cx, p, out.Z)) return false;
    160169
    161170    return true;
     
    163172
    164173template<> jsval ScriptInterface::ToJSVal<CFixedVector3D>(JSContext* cx, const CFixedVector3D& val)
    165174{
     175    JSAutoRequest rq(cx);
     176
    166177    // apply the Vector3D prototype to the return value;
    167178    ScriptInterface::CxPrivate* pCxPrivate = ScriptInterface::GetScriptInterfaceAndCBData(cx);
    168179    JSObject* obj = JS_NewObject(cx, NULL, JSVAL_TO_OBJECT(pCxPrivate->pScriptInterface->GetCachedValue(ScriptInterface::CACHE_VECTOR3DPROTO).get()), NULL);
     
    170181    if (!obj)
    171182        return JSVAL_VOID;
    172183
    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));
    176187
    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());
    180191
    181192    return OBJECT_TO_JSVAL(obj);
    182193}
    183194
    184195template<> bool ScriptInterface::FromJSVal<CFixedVector2D>(JSContext* cx, jsval v, CFixedVector2D& out)
    185196{
    186     if (!JSVAL_IS_OBJECT(v))
     197    JSAutoRequest rq(cx);
     198    if (JSVAL_IS_PRIMITIVE(v))
    187199        return false; // TODO: report type error
    188200    JSObject* obj = JSVAL_TO_OBJECT(v);
    189201
    190     jsval p;
     202    JS::RootedValue p(cx);
    191203
    192     if (!JS_GetProperty(cx, obj, "x", &p)) return false; // TODO: report type errors
     204    if (!JS_GetProperty(cx, obj, "x", p.address())) return false; // TODO: report type errors
    193205    if (!FromJSVal(cx, p, out.X)) return false;
    194206
    195     if (!JS_GetProperty(cx, obj, "y", &p)) return false;
     207    if (!JS_GetProperty(cx, obj, "y", p.address())) return false;
    196208    if (!FromJSVal(cx, p, out.Y)) return false;
    197209
    198210    return true;
     
    200212
    201213template<> jsval ScriptInterface::ToJSVal<CFixedVector2D>(JSContext* cx, const CFixedVector2D& val)
    202214{
     215    JSAutoRequest rq(cx);
     216
    203217    // apply the Vector2D prototype to the return value
    204218    ScriptInterface::CxPrivate* pCxPrivate = ScriptInterface::GetScriptInterfaceAndCBData(cx);
    205219    JSObject* obj = JS_NewObject(cx, NULL, JSVAL_TO_OBJECT(pCxPrivate->pScriptInterface->GetCachedValue(ScriptInterface::CACHE_VECTOR2DPROTO).get()), NULL);
     
    207221    if (!obj)
    208222        return JSVAL_VOID;
    209223
    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));
    212226
    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());
    215229
    216230    return OBJECT_TO_JSVAL(obj);
    217231}
    218232
    219 template<jsint atype, typename T> jsval ToJSVal_Grid(JSContext* cx, const Grid<T>& val)
     233template<> jsval ScriptInterface::ToJSVal<Grid<u8> >(JSContext* cx, const Grid<u8>& val)
    220234{
    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);
    224240
    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));
    229244
    230     js::TypedArray *tdest = js::TypedArray::fromJSObject(darray);
    231     ENSURE(tdest->byteLength == len*sizeof(T));
    232245
    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());
    234250
    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 
    243251    return OBJECT_TO_JSVAL(obj);
    244252}
     253 
     254template<> 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));
    245265
    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());
    250270
    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);
    254272}
  • source/simulation2/scripting/MessageTypeConversions.cpp

     
    2121#include "scriptinterface/ScriptInterface.h"
    2222#include "simulation2/MessageTypes.h"
    2323
    24 #include "js/jsapi.h"
    25 
    2624#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    }
    3032
    3133#define SET_MSG_PROPERTY(name) \
    3234    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())) \
    3539            return JSVAL_VOID; \
    3640    } while (0);
    3741
    3842#define FROMJSVAL_SETUP() \
    39     if (! JSVAL_IS_OBJECT(val)) \
     43    if ( JSVAL_IS_PRIMITIVE(val)) \
    4044        return NULL; \
    4145    JSObject* obj = JSVAL_TO_OBJECT(val); \
    42     jsval prop;
     46    JS::RootedValue prop(scriptInterface.GetContext());
    4347
    4448#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())) \
    4653        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    }
    5057
    5158jsval CMessage::ToJSValCached(ScriptInterface& scriptInterface) const
    5259{
  • source/simulation2/serialization/BinarySerializer.cpp

     
    1919
    2020#include "BinarySerializer.h"
    2121
    22 #include "SerializedScriptTypes.h"
    23 
    2422#include "lib/alignment.h"
    2523#include "ps/CLogger.h"
    2624
    2725#include "scriptinterface/ScriptInterface.h"
    2826#include "scriptinterface/ScriptExtraHeaders.h" // for JSDOUBLE_IS_INT32, typed arrays
     27#include "SerializedScriptTypes.h"
    2928
    30 static u8 GetArrayType(uint32 arrayType)
     29static u8 GetArrayType(JSArrayBufferViewType arrayType)
    3130{
    3231    switch(arrayType)
    3332    {
    34     case js::TypedArray::TYPE_INT8:
     33    case JSArrayBufferViewType::TYPE_INT8:
    3534        return SCRIPT_TYPED_ARRAY_INT8;
    36     case js::TypedArray::TYPE_UINT8:
     35    case JSArrayBufferViewType::TYPE_UINT8:
    3736        return SCRIPT_TYPED_ARRAY_UINT8;
    38     case js::TypedArray::TYPE_INT16:
     37    case JSArrayBufferViewType::TYPE_INT16:
    3938        return SCRIPT_TYPED_ARRAY_INT16;
    40     case js::TypedArray::TYPE_UINT16:
     39    case JSArrayBufferViewType::TYPE_UINT16:
    4140        return SCRIPT_TYPED_ARRAY_UINT16;
    42     case js::TypedArray::TYPE_INT32:
     41    case JSArrayBufferViewType::TYPE_INT32:
    4342        return SCRIPT_TYPED_ARRAY_INT32;
    44     case js::TypedArray::TYPE_UINT32:
     43    case JSArrayBufferViewType::TYPE_UINT32:
    4544        return SCRIPT_TYPED_ARRAY_UINT32;
    46     case js::TypedArray::TYPE_FLOAT32:
     45    case JSArrayBufferViewType::TYPE_FLOAT32:
    4746        return SCRIPT_TYPED_ARRAY_FLOAT32;
    48     case js::TypedArray::TYPE_FLOAT64:
     47    case JSArrayBufferViewType::TYPE_FLOAT64:
    4948        return SCRIPT_TYPED_ARRAY_FLOAT64;
    50     case js::TypedArray::TYPE_UINT8_CLAMPED:
     49    case JSArrayBufferViewType::TYPE_UINT8_CLAMPED:
    5150        return SCRIPT_TYPED_ARRAY_UINT8_CLAMPED;
    5251    default:
    5352        LOGERROR(L"Cannot serialize unrecognized typed array view: %d", arrayType);
     
    5655}
    5756
    5857CBinarySerializerScriptImpl::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()),
    6059    m_ScriptBackrefsArena(1 * MiB), m_ScriptBackrefs(backrefs_t::key_compare(), ScriptBackrefsAlloc(m_ScriptBackrefsArena)), m_ScriptBackrefsNext(1)
    6160{
    6261}
    63 
     62// TODO YGW: Test serialization...
    6463void CBinarySerializerScriptImpl::HandleScriptVal(jsval val)
    6564{
    6665    JSContext* cx = m_ScriptInterface.GetContext();
     66    JSAutoRequest rq(cx);
    6767
    6868    switch (JS_TypeOfValue(cx, val))
    6969    {
     
    8585            break;
    8686        }
    8787
    88         JSObject* obj = JSVAL_TO_OBJECT(val);
     88        //JSObject* obj = JSVAL_TO_OBJECT(val);
     89        JS::RootedObject obj(cx, JSVAL_TO_OBJECT(val));
    8990
    9091        // If we've already serialized this object, just output a reference to it
    9192        u32 tag = GetScriptBackrefTag(obj);
     
    104105
    105106            // Arrays like [1, 2, ] have an 'undefined' at the end which is part of the
    106107            // length but seemingly isn't enumerated, so store the length explicitly
    107             jsuint length = 0;
     108            uint length = 0;
    108109            if (!JS_GetArrayLength(cx, obj, &length))
    109110                throw PSERROR_Serialize_ScriptError("JS_GetArrayLength failed");
    110111            m_Serializer.NumberU32_Unbounded("array length", length);
    111112        }
    112         else if (js_IsTypedArray(obj))
     113        //JS_IsArrayBufferViewObject()
     114        //JS_IsTypedArrayObject()
     115        else if (JS_IsTypedArrayObject(obj))
    113116        {
    114117            m_Serializer.NumberU8_Unbounded("type", SCRIPT_TYPE_TYPED_ARRAY);
    115118
    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));
    121122
    122123            // Now handle its array buffer
    123124            // 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)));
    125126            break;
    126127        }
    127         else if (js_IsArrayBuffer(obj))
     128        else if (JS_IsArrayBufferObject(obj))
    128129        {
    129130            m_Serializer.NumberU8_Unbounded("type", SCRIPT_TYPE_ARRAY_BUFFER);
    130131
    131             js::ArrayBuffer* arrayBuffer = js::ArrayBuffer::fromJSObject(obj);
    132 
    133132#if BYTE_ORDER != LITTLE_ENDIAN
    134133#error TODO: need to convert JS ArrayBuffer data to little-endian
    135134#endif
    136135
    137             u32 length = arrayBuffer->byteLength;
     136            u32 length = JS_GetArrayBufferByteLength(obj);
    138137            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);
    140139            break;
    141140        }
    142141        else
    143142        {
    144143            // Find type of object
    145             JSClass* jsclass = JS_GET_CLASS(cx, obj);
     144            JSClass* jsclass = JS_GetClass(obj);
    146145            if (!jsclass)
    147                 throw PSERROR_Serialize_ScriptError("JS_GET_CLASS failed");
     146                throw PSERROR_Serialize_ScriptError("JS_GetClass failed");
    148147            JSProtoKey protokey = JSCLASS_CACHED_PROTO_KEY(jsclass);
    149148
    150149            if (protokey == JSProto_Object)
    151150            {
    152151                // 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());
    154154                if (!proto)
    155155                    throw PSERROR_Serialize_ScriptError("JS_GetPrototype failed");
    156156
     
    175175                    JSBool hasCustomSerialize;
    176176                    if (!JS_HasProperty(cx, obj, "Serialize", &hasCustomSerialize))
    177177                        throw PSERROR_Serialize_ScriptError("JS_HasProperty failed");
    178                    
     178
    179179                    if (hasCustomSerialize)
    180180                    {
    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()))
    183183                            throw PSERROR_Serialize_ScriptError("JS_LookupProperty failed");
    184184
    185185                        // If serialize is null, so don't serialize anything more
     
    199199                // Standard Number object
    200200                m_Serializer.NumberU8_Unbounded("type", SCRIPT_TYPE_OBJECT_NUMBER);
    201201                // Get primitive value
    202                 jsdouble d;
     202                double d;
    203203                if (!JS_ValueToNumber(cx, val, &d))
    204204                    throw PSERROR_Serialize_ScriptError("JS_ValueToNumber failed");
    205205                m_Serializer.NumberDouble_Unbounded("value", d);
     
    224224                JSBool b;
    225225                if (!JS_ValueToBoolean(cx, val, &b))
    226226                    throw PSERROR_Serialize_ScriptError("JS_ValueToBoolean failed");
    227                 m_Serializer.Bool("value", b == JS_TRUE);
     227                m_Serializer.Bool("value", b);
    228228                break;
    229229            }
    230230            else
     
    240240        // (Note that we don't do any rooting, because we assume nothing is going to trigger GC.
    241241        // I'm not absolute certain that's necessarily a valid assumption.)
    242242
    243         AutoJSIdArray ida (cx, JS_Enumerate(cx, obj));
    244         if (!ida.get())
     243        JS::AutoIdArray ida (cx, JS_Enumerate(cx, obj));
     244        if (!ida)
    245245            throw PSERROR_Serialize_ScriptError("JS_Enumerate failed");
    246246
    247247        m_Serializer.NumberU32_Unbounded("num props", (uint32_t)ida.length());
     
    250250        {
    251251            jsid id = ida[i];
    252252
    253             jsval idval, propval;
    254 
     253            JS::RootedValue idval(cx);
     254            JS::RootedValue propval(cx);
     255           
    255256            // Get the property name as a string
    256             if (!JS_IdToValue(cx, id, &idval))
     257            if (!JS_IdToValue(cx, id, idval.address()))
    257258                throw PSERROR_Serialize_ScriptError("JS_IdToValue failed");
    258             JSString* idstr = JS_ValueToString(cx, idval);
     259            JSString* idstr = JS_ValueToString(cx, idval.get());
    259260            if (!idstr)
    260261                throw PSERROR_Serialize_ScriptError("JS_ValueToString failed");
    261262
     
    263264
    264265            // Use LookupProperty instead of GetProperty to avoid the danger of getters
    265266            // (they might delete values and trigger GC)
    266             if (!JS_LookupPropertyById(cx, obj, id, &propval))
     267            if (!JS_LookupPropertyById(cx, obj, id, propval.address()))
    267268                throw PSERROR_Serialize_ScriptError("JS_LookupPropertyById failed");
    268269
    269270            HandleScriptVal(propval);
     
    308309        else
    309310        {
    310311            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));
    326314        }
    327315        break;
    328316    }
    329317    case JSTYPE_BOOLEAN:
    330318    {
    331319        m_Serializer.NumberU8_Unbounded("type", SCRIPT_TYPE_BOOLEAN);
    332         JSBool b = JSVAL_TO_BOOLEAN(val);
     320        bool b = JSVAL_TO_BOOLEAN(val);
    333321        m_Serializer.NumberU8_Unbounded("value", b ? 1 : 0);
    334322        break;
    335323    }
    336     case JSTYPE_XML:
    337     {
    338         LOGERROR(L"Cannot serialise JS objects of type 'xml'");
    339         throw PSERROR_Serialize_InvalidScriptValue();
    340     }
    341324    default:
    342325    {
    343326        debug_warn(L"Invalid TypeOfValue");
     
    349332void CBinarySerializerScriptImpl::ScriptString(const char* name, JSString* string)
    350333{
    351334    JSContext* cx = m_ScriptInterface.GetContext();
     335    JSAutoRequest rq(cx);
     336
    352337    size_t length;
    353338    const jschar* chars = JS_GetStringCharsAndLength(cx, string, &length);
    354339
     
    382367
    383368    // If it was newly inserted, we need to make sure it gets rooted
    384369    // 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);
    386373    m_ScriptBackrefsNext++;
    387374    // Return a non-tag number so callers know they need to serialize the object
    388375    return 0;
  • source/simulation2/serialization/BinarySerializer.h

     
    2020
    2121#include "ISerializer.h"
    2222
    23 #include "scriptinterface/AutoRooters.h"
    24 
    2523#include "lib/byte_order.h"
    2624#include "lib/allocators/arena.h"
    2725
     
    7371    u32 m_ScriptBackrefsNext;
    7472    u32 GetScriptBackrefTag(JSObject* obj);
    7573
    76     AutoGCRooter m_Rooter;
     74    JS::AutoObjectVector m_Rooter;
    7775
    7876    std::map<JSObject*, std::wstring> m_SerializablePrototypes;
    7977
  • source/simulation2/serialization/StdDeserializer.cpp

     
    2525#include "scriptinterface/ScriptInterface.h"
    2626#include "scriptinterface/ScriptExtraHeaders.h" // for typed arrays
    2727
    28 #include "js/jsapi.h"
    29 
    3028#include "lib/byte_order.h"
    3129
    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 
    5930CStdDeserializer::CStdDeserializer(ScriptInterface& scriptInterface, std::istream& stream) :
    6031    m_ScriptInterface(scriptInterface), m_Stream(stream)
    6132{
     
    138109
    139110void CStdDeserializer::FreeScriptBackrefs()
    140111{
     112    JSContext* cx = m_ScriptInterface.GetContext();
     113    JSAutoRequest rq(cx);
     114   
    141115    std::map<u32, JSObject*>::iterator it = m_ScriptBackrefs.begin();
    142116    for (; it != m_ScriptBackrefs.end(); ++it)
    143117    {
    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);
    146119    }
    147120    m_ScriptBackrefs.clear();
    148121}
     
    152125jsval CStdDeserializer::ReadScriptVal(const char* UNUSED(name), JSObject* appendParent)
    153126{
    154127    JSContext* cx = m_ScriptInterface.GetContext();
     128   
     129    JSAutoRequest rq(cx);
    155130
    156131    uint8_t type;
    157132    NumberU8_Unbounded("type", type);
     
    192167            if (!proto)
    193168                throw PSERROR_Deserialize_ScriptError("Failed to find serializable prototype for object");
    194169
    195             JSObject* parent = JS_GetParent(cx, proto);
     170            JSObject* parent = JS_GetParent(proto);
    196171            if (!proto || !parent)
    197172                throw PSERROR_Deserialize_ScriptError();
    198173
     
    206181            JSBool hasCustomDeserialize, hasCustomSerialize;
    207182            if (!JS_HasProperty(cx, obj, "Serialize", &hasCustomSerialize) || !JS_HasProperty(cx, obj, "Deserialize", &hasCustomDeserialize))
    208183                throw PSERROR_Serialize_ScriptError("JS_HasProperty failed");
    209            
     184
    210185            if (hasCustomDeserialize)
    211186            {
    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()))
    214189                    throw PSERROR_Serialize_ScriptError("JS_LookupProperty failed");
    215190                bool hasNullSerialize = hasCustomSerialize && JSVAL_IS_NULL(serialize);
    216191
     
    241216            utf16string propname;
    242217            ReadStringUTF16("prop name", propname);
    243218
    244             jsval propval = ReadScriptVal("prop value", NULL);
     219            JS::RootedValue propval(cx, ReadScriptVal("prop value", NULL));
    245220            CScriptValRooted propvalRoot(cx, propval);
    246221
    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()))
    248223                throw PSERROR_Deserialize_ScriptError();
    249224        }
    250225
     
    266241    {
    267242        double value;
    268243        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))
    271246            throw PSERROR_Deserialize_ScriptError("JS_NewNumberValue failed");
    272247        return rval;
    273248    }
     
    275250    {
    276251        uint8_t value;
    277252        NumberU8("value", value, 0, 1);
    278         return BOOLEAN_TO_JSVAL(value ? JS_TRUE : JS_FALSE);
     253        return BOOLEAN_TO_JSVAL(value ? true : false);
    279254    }
    280255    case SCRIPT_TYPE_BACKREF:
    281256    {
     
    290265    {
    291266        double value;
    292267        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));
    296269        CScriptValRooted objRoot(cx, val);
    297270
    298271        JSObject* ctorobj;
    299         if (!JS_GetClassObject(cx, JS_GetGlobalObject(cx), JSProto_Number, &ctorobj))
     272        if (!JS_GetClassObject(cx, JS_GetGlobalForScopeChain(cx), JSProto_Number, &ctorobj))
    300273            throw PSERROR_Deserialize_ScriptError("JS_GetClassObject failed");
    301274
    302         JSObject* obj = JS_New(cx, ctorobj, 1, &val);
     275        JSObject* obj = JS_New(cx, ctorobj, 1, val.address());
    303276        if (!obj)
    304277            throw PSERROR_Deserialize_ScriptError("JS_New failed");
    305278        AddScriptBackref(obj);
     
    311284        ScriptString("value", str);
    312285        if (!str)
    313286            throw PSERROR_Deserialize_ScriptError();
    314         jsval val = STRING_TO_JSVAL(str);
     287        JS::RootedValue val(cx, STRING_TO_JSVAL(str));
    315288        CScriptValRooted valRoot(cx, val);
    316289
    317290        JSObject* ctorobj;
    318         if (!JS_GetClassObject(cx, JS_GetGlobalObject(cx), JSProto_String, &ctorobj))
     291        if (!JS_GetClassObject(cx, JS_GetGlobalForScopeChain(cx), JSProto_String, &ctorobj))
    319292            throw PSERROR_Deserialize_ScriptError("JS_GetClassObject failed");
    320293
    321         JSObject* obj = JS_New(cx, ctorobj, 1, &val);
     294        JSObject* obj = JS_New(cx, ctorobj, 1, val.address());
    322295        if (!obj)
    323296            throw PSERROR_Deserialize_ScriptError("JS_New failed");
    324297        AddScriptBackref(obj);
     
    328301    {
    329302        bool value;
    330303        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));
    333305
    334306        JSObject* ctorobj;
    335         if (!JS_GetClassObject(cx, JS_GetGlobalObject(cx), JSProto_Boolean, &ctorobj))
     307        if (!JS_GetClassObject(cx, JS_GetGlobalForScopeChain(cx), JSProto_Boolean, &ctorobj))
    336308            throw PSERROR_Deserialize_ScriptError("JS_GetClassObject failed");
    337309
    338         JSObject* obj = JS_New(cx, ctorobj, 1, &val);
     310        JSObject* obj = JS_New(cx, ctorobj, 1, val.address());
    339311        if (!obj)
    340312            throw PSERROR_Deserialize_ScriptError("JS_New failed");
    341313        AddScriptBackref(obj);
     
    354326
    355327        // Get buffer object
    356328        jsval bufferVal = ReadScriptVal("buffer", NULL);
    357         CScriptValRooted bufferValRoot(cx, bufferVal);
    358329
    359         if (!JSVAL_IS_OBJECT(bufferVal))
     330        if (JSVAL_IS_PRIMITIVE(bufferVal))
    360331            throw PSERROR_Deserialize_ScriptError();
    361332
    362333        JSObject* bufferObj = JSVAL_TO_OBJECT(bufferVal);
    363         if (!js_IsArrayBuffer(bufferObj))
     334        if (!JS_IsArrayBufferObject(bufferObj))
    364335            throw PSERROR_Deserialize_ScriptError("js_IsArrayBuffer failed");
    365336
    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        }
    367370        if (!arrayObj)
    368371            throw PSERROR_Deserialize_ScriptError("js_CreateTypedArrayWithBuffer failed");
    369372
     
    383386#error TODO: need to convert JS ArrayBuffer data from little-endian
    384387#endif
    385388
    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);
    390390        AddScriptBackref(bufferObj);
    391391
    392         js::ArrayBuffer* buffer = js::ArrayBuffer::fromJSObject(bufferObj);
    393         memcpy(buffer->data, bufferData, length);
    394         delete[] bufferData;
    395 
    396392        return OBJECT_TO_JSVAL(bufferObj);
    397393    }
    398394    default:
     
    440436
    441437void CStdDeserializer::ScriptObjectAppend(const char* name, jsval& obj)
    442438{
    443     if (!JSVAL_IS_OBJECT(obj))
     439    if (JSVAL_IS_PRIMITIVE(obj))
    444440        throw PSERROR_Deserialize_ScriptError();
    445441
    446442    ReadScriptVal(name, JSVAL_TO_OBJECT(obj));
  • source/simulation2/system/ComponentManager.cpp

     
    243243
    244244    // Find all the ctor prototype's On* methods, and subscribe to the appropriate messages:
    245245
    246     CScriptVal proto;
     246    JS::RootedObject proto(componentManager->m_ScriptInterface.GetContext());
    247247    if (!componentManager->m_ScriptInterface.GetProperty(ctor.get(), "prototype", proto))
    248248        return; // error
    249249
    250250    std::vector<std::string> methods;
    251     if (!componentManager->m_ScriptInterface.EnumeratePropertyNamesWithPrefix(proto.get(), "On", methods))
     251    if (!componentManager->m_ScriptInterface.EnumeratePropertyNamesWithPrefix(proto, "On", methods))
    252252        return; // error
    253253
    254254    for (std::vector<std::string>::const_iterator it = methods.begin(); it != methods.end(); ++it)
     
    289289        {
    290290            jsval instance = eit->second->GetJSInstance();
    291291            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            }
    293296        }
    294297    }
    295298}
     
    616619    jsval obj = JSVAL_NULL;
    617620    if (ct.type == CT_Script)
    618621    {
    619         obj = m_ScriptInterface.CallConstructor(ct.ctor.get(), JSVAL_VOID);
     622        obj = m_ScriptInterface.CallConstructor(ct.ctor.get(), 0, JSVAL_VOID);
    620623        if (JSVAL_IS_VOID(obj))
    621624        {
    622625            LOGERROR(L"Script component constructor failed");
  • source/simulation2/system/ComponentManager.h

     
    9696    void RegisterComponentType(InterfaceId, ComponentTypeId, AllocFunc, DeallocFunc, const char*, const std::string& schema);
    9797    void RegisterComponentTypeScriptWrapper(InterfaceId, ComponentTypeId, AllocFunc, DeallocFunc, const char*, const std::string& schema);
    9898
     99
     100    void Tick() { m_ScriptInterface.Tick(); };
    99101    /**
    100102     * Subscribe the current component type to the given message type.
    101103     * Each component's HandleMessage will be called on any BroadcastMessage of this message type,
  • source/simulation2/system/InterfaceScripted.h

     
    1919#define INCLUDED_INTERFACE_SCRIPTED
    2020
    2121#include "scriptinterface/ScriptInterface.h"
    22 #include "js/jsapi.h"
    2322
    2423#define BEGIN_INTERFACE_WRAPPER(iname) \
    2524    JSClass class_ICmp##iname = { \
    2625        "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 \
    3028    }; \
    3129    static JSFunctionSpec methods_ICmp##iname[] = {
    3230
     
    3533    }; \
    3634    void ICmp##iname::InterfaceInit(ScriptInterface& scriptInterface) { \
    3735        JSContext* cx = scriptInterface.GetContext(); \
    38         JSObject* global = JS_GetGlobalObject(cx); \
     36        JSAutoRequest rq(cx); \
     37        JSObject* global = JS_GetGlobalForScopeChain(cx); \
    3938        JS_InitClass(cx, global, NULL, &class_ICmp##iname, NULL, 0, NULL, methods_ICmp##iname, NULL, NULL); \
    4039    } \
    4140    JSClass* ICmp##iname::GetJSClass() const { return &class_ICmp##iname; } \
     
    4544
    4645#define DEFINE_INTERFACE_METHOD_0(scriptname, rettype, classname, methodname) \
    4746    { scriptname, \
    48         ScriptInterface::callMethod<rettype, &class_##classname, classname, &classname::methodname>, \
     47        { ScriptInterface::callMethod<rettype, &class_##classname, classname, &classname::methodname>, NULL }, \
    4948        0, \
    5049        JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT },
    5150
    5251#define DEFINE_INTERFACE_METHOD_1(scriptname, rettype, classname, methodname, arg1) \
    5352    { scriptname, \
    54         ScriptInterface::callMethod<rettype, arg1, &class_##classname, classname, &classname::methodname>, \
     53        { ScriptInterface::callMethod<rettype, arg1, &class_##classname, classname, &classname::methodname>, NULL}, \
    5554        1, \
    5655        JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT },
    5756
    5857#define DEFINE_INTERFACE_METHOD_2(scriptname, rettype, classname, methodname, arg1, arg2) \
    5958    { scriptname, \
    60         ScriptInterface::callMethod<rettype, arg1, arg2, &class_##classname, classname, &classname::methodname>, \
     59        { ScriptInterface::callMethod<rettype, arg1, arg2, &class_##classname, classname, &classname::methodname>, NULL }, \
    6160        2, \
    6261        JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT },
    6362
    6463#define DEFINE_INTERFACE_METHOD_3(scriptname, rettype, classname, methodname, arg1, arg2, arg3) \
    6564    { 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 }, \
    6766        3, \
    6867        JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT },
    6968
    7069#define DEFINE_INTERFACE_METHOD_4(scriptname, rettype, classname, methodname, arg1, arg2, arg3, arg4) \
    7170    { 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 }, \
    7372        4, \
    7473        JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT },
    7574
    7675#define DEFINE_INTERFACE_METHOD_5(scriptname, rettype, classname, methodname, arg1, arg2, arg3, arg4, arg5) \
    7776    { 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 }, \
    7978        5, \
    8079        JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT },
    8180
    8281#define DEFINE_INTERFACE_METHOD_6(scriptname, rettype, classname, methodname, arg1, arg2, arg3, arg4, arg5, arg6) \
    8382    { 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 }, \
    8584        6, \
    8685        JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT },
    8786
    8887#define DEFINE_INTERFACE_METHOD_7(scriptname, rettype, classname, methodname, arg1, arg2, arg3, arg4, arg5, arg6, arg7) \
    8988    { 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 }, \
    9190        7, \
    9291        JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT },
    9392
  • source/simulation2/system/ParamNode.cpp

     
    2525#include "ps/Filesystem.h"
    2626#include "ps/XML/Xeromyces.h"
    2727
    28 #include "js/jsapi.h"
    29 
    3028#include <sstream>
    3129
    3230// Disable "'boost::algorithm::detail::is_classifiedF' : assignment operator could not be generated"
     
    328326
    329327jsval CParamNode::ConstructJSVal(JSContext* cx) const
    330328{
     329    JSAutoRequest rq(cx);
    331330    if (m_Childs.empty())
    332331    {
    333332        // Empty node - map to undefined
     
    351350
    352351    for (std::map<std::string, CParamNode>::const_iterator it = m_Childs.begin(); it != m_Childs.end(); ++it)
    353352    {
    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()))
    356355            return JSVAL_VOID; // TODO: report error
    357356    }
    358357
     
    363362        JSString* str = JS_InternUCStringN(cx, reinterpret_cast<const jschar*>(text.data()), text.length());
    364363        if (!str)
    365364            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()))
    368367            return JSVAL_VOID; // TODO: report error
    369368    }
    370369