diff --git a/CMakeLists.txt b/CMakeLists.txt index d2693c74..8d7760be 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,7 +29,6 @@ project(d2bs) option(MOZJS_USE_PREBUILT "Use the prebuilt release library of mozjs (vendor/mozjs-prebuilt)" OFF) -#add_subdirectory(sandbox) add_subdirectory(vendor) if (NOT CMAKE_BUILD_TYPE) @@ -106,7 +105,7 @@ set(D2BS_SRCS add_library(D2BS SHARED ${D2BS_SRCS}) -target_compile_options(D2BS PRIVATE /W4) +target_compile_options(D2BS PRIVATE /W4 /utf-8) target_include_directories(D2BS PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src" diff --git a/CMakePresets.json b/CMakePresets.json index 6de3a6a3..468ab71e 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -10,8 +10,7 @@ "installDir": "${sourceDir}/out/install/${presetName}", "cacheVariables": { "CMAKE_C_COMPILER": "cl.exe", - "CMAKE_CXX_COMPILER": "cl.exe", - "MOZJS_USE_PREBUILT": true + "CMAKE_CXX_COMPILER": "cl.exe" }, "condition": { "type": "equals", @@ -35,7 +34,10 @@ "displayName": "x86 Distribute", "description": "Target Windows (32-bit) with the Visual Studio development environment.", "inherits": "x86-debug", - "cacheVariables": { "CMAKE_BUILD_TYPE": "Release" } + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Release", + "MOZJS_USE_PREBUILT": true + } }, { "name": "x86-relwithdebinfo", diff --git a/dist/d2bs/kolbot/libs/SoloPlay/Functions/AttackOverrides.js b/dist/d2bs/kolbot/libs/SoloPlay/Functions/AttackOverrides.js index 22bee0d6..a535baf5 100644 --- a/dist/d2bs/kolbot/libs/SoloPlay/Functions/AttackOverrides.js +++ b/dist/d2bs/kolbot/libs/SoloPlay/Functions/AttackOverrides.js @@ -1633,7 +1633,10 @@ Attack.pwnDia = function () { if (me.mp > manaStatic + manaTP + manaTP && diabloMissiles.length < 3 && !dia.attacking && dia.hpPercent > Config.CastStatic) { - let [x, y] = me; + // BUG: me is not iterable + //let [x, y] = me; + let x = me.x; + let y = me.y; ClassAttack.switchCurse(dia, true); // curse him if we can // re-check his mode if (!dia.attacking) { diff --git a/sandbox/CMakeLists.txt b/sandbox/CMakeLists.txt deleted file mode 100644 index 40cf628a..00000000 --- a/sandbox/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -add_executable(sandbox main.cpp) -target_link_libraries(sandbox PRIVATE js) -install(TARGETS sandbox RUNTIME DESTINATION bin) diff --git a/sandbox/main.cpp b/sandbox/main.cpp deleted file mode 100644 index 191d505d..00000000 --- a/sandbox/main.cpp +++ /dev/null @@ -1,124 +0,0 @@ -#pragma warning(push, 0) -#include -#include -#include -#pragma warning(pop) - -class A { - public: - A(JS::HandleObject obj) { - JS_SetReservedSlot(obj, 0, JS::PrivateValue(this)); - printf("A\n"); - } - - virtual ~A() { - printf("~A\n"); - } - - static JSObject* Instantiate(JSContext* cx) { - JS::RootedObject global(cx, JS::CurrentGlobalOrNull(cx)); - JS::RootedValue constructor_val(cx); - if (!JS_GetProperty(cx, global, "A", &constructor_val)) { - JS_ReportErrorASCII(cx, "Could not find constructor object for A"); - return nullptr; - } - if (!constructor_val.isObject()) { - JS_ReportErrorASCII(cx, "A is not a constructor"); - return nullptr; - } - JS::RootedObject constructor(cx, &constructor_val.toObject()); - - JS::RootedObject obj(cx, JS_New(cx, constructor, JS::HandleValueArray::empty())); - if (!obj) { - JS_ReportErrorASCII(cx, "Calling A constructor failed"); - return nullptr; - } - return obj; - } - - static bool New(JSContext* cx, unsigned argc, JS::Value* vp) { - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); - JS::RootedObject newObject(cx, JS_NewObjectForConstructor(cx, &Aclass, args)); - A* a = new A(newObject); - args.rval().setObject(*newObject); - return true; - } - - static inline void finalize(JSFreeOp* fop, JSObject* obj) { - printf("finalize\n"); - JS::Value val = JS_GetReservedSlot(obj, 0); - if (val.isDouble()) { - A* a = static_cast(val.toPrivate()); - delete a; - } - } - - static inline JSClassOps Aops = { - .addProperty = nullptr, - .delProperty = nullptr, - .enumerate = nullptr, - .newEnumerate = nullptr, - .resolve = nullptr, - .mayResolve = nullptr, - .finalize = finalize, - .call = nullptr, - .hasInstance = nullptr, - .construct = nullptr, - .trace = nullptr, - }; - static inline JSClass Aclass = { - "A", - JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_FOREGROUND_FINALIZE, - &Aops, - }; -}; - -const JSClassOps DefaultGlobalClassOps = { - nullptr, // addProperty - nullptr, // deleteProperty - nullptr, // enumerate - JS_NewEnumerateStandardClasses, // newEnumerate - JS_ResolveStandardClass, // resolve - JS_MayResolveStandardClass, // mayResolve - nullptr, // finalize - nullptr, // call - nullptr, // hasInstance - nullptr, // construct - JS_GlobalObjectTraceHook // trace -}; - -int main() { - JS_Init(); - JSContext* cx = JS_NewContext(JS::DefaultHeapMaxBytes); - - js::UseInternalJobQueues(cx); - JS::InitSelfHostedCode(cx); - JS::PersistentRootedObject persistent; - - { - JSAutoRequest request(cx); - JS::CompartmentOptions global_options; - static JSClass kGlobalClass{"D2BSGlobal", JSCLASS_GLOBAL_FLAGS, &DefaultGlobalClassOps}; - JS::RootedObject global(cx, JS_NewGlobalObject(cx, &kGlobalClass, nullptr, JS::FireOnNewGlobalHook, global_options)); - JSAutoCompartment ac(cx, global); - - JS_InitClass(cx, global, nullptr, &A::Aclass, A::New, 0, nullptr, nullptr, nullptr, nullptr); - - persistent.init(cx, A::Instantiate(cx)); - - JS::CompileOptions options(cx); - options.setFileAndLine("", 1); - - std::string source(R"js( - const a = new A; - )js"); - - JS::RootedValue rval(cx); - JS::Evaluate(cx, options, source.c_str(), source.length(), &rval); - } - - JS_DestroyContext(cx); - - JS_ShutDown(); - return 0; -} diff --git a/src/Engine.cc b/src/Engine.cc index f916c233..11860312 100644 --- a/src/Engine.cc +++ b/src/Engine.cc @@ -227,7 +227,7 @@ void Engine::OnGameEntered() { if (!Vars.bUseProfileScript) { const char* starter = GetStarterScriptName(); if (starter != NULL) { - Print("ÿc2D2BSÿc0 :: Starting %s", starter); + Print("\u00FFc2D2BS\u00FFc0 :: Starting %s", starter); if (StartScript(starter, GetStarterScriptState())) Print("ÿc2D2BSÿc0 :: %s running.", starter); else @@ -240,7 +240,7 @@ void Engine::OnMenuEntered(bool beginStarter) { if (beginStarter && !Vars.bUseProfileScript) { const char* starter = GetStarterScriptName(); if (starter != NULL) { - Print("ÿc2D2BSÿc0 :: Starting %s", starter); + Print("\u00FFc2D2BS\u00FFc0 :: Starting %s", starter); if (StartScript(starter, GetStarterScriptState())) Print("ÿc2D2BSÿc0 :: %s running.", starter); else @@ -281,14 +281,10 @@ void Engine::FlushPrint() { std::wstring wstr = AnsiToWide(*it); D2CLIENT_PrintGameString(wstr.c_str(), 0); } - /*} else if (Vars.bUseGamePrint && ClientState() == ClientStateMenu && findControl(4, (const wchar_t*)NULL, -1, 28, 410, 354, 298)) { - while (getline(ss, temp)) - SplitLines(temp, Console::MaxWidth() - 100, ' ', lines); - // TODO: Double check this function, make sure it is working as intended. - for (list::iterator it = lines.begin(); it != lines.end(); ++it) - D2MULTI_PrintChannelText((char*)it->c_str(), 0);*/ } else { - while (getline(ss, temp)) Console::AddLine(temp); + while (getline(ss, temp)) { + Console::AddLine(temp); + } } clean.pop(); diff --git a/src/Spidermonkey Engine/Core/JS/JSControl.cpp b/src/Spidermonkey Engine/Core/JS/JSControl.cpp index f6698787..0b679e31 100644 --- a/src/Spidermonkey Engine/Core/JS/JSControl.cpp +++ b/src/Spidermonkey Engine/Core/JS/JSControl.cpp @@ -2,6 +2,7 @@ #include "Bindings.h" #include "D2Helpers.h" // ClientState +#include "StringWrap.h" JSObject* ControlWrap::Instantiate(JSContext* ctx, D2WinControlStrc* control) { JS::RootedObject global(ctx, JS::CurrentGlobalOrNull(ctx)); @@ -100,12 +101,11 @@ bool ControlWrap::SetText(JSContext* ctx, JS::CallArgs& args) { UNWRAP_CONTROL_OR_ERROR(ctx, &ctrl, args.thisv()); if (ctrl->dwType == 1 && args[0].isString()) { - char* szText = JS_EncodeString(ctx, args[0].toString()); + StringWrap szText(ctx, args[0]); if (!szText) { THROW_ERROR(ctx, "failed to encode string"); } setControlText(ctrl, szText); - JS_free(ctx, szText); } args.rval().setUndefined(); return true; @@ -362,13 +362,12 @@ bool ControlWrap::FreeSetText(JSContext* ctx, JS::CallArgs& args) { return true; } - char* szText = JS_EncodeString(ctx, args[0].toString()); + StringWrap szText(ctx, args[0]); if (!szText) { args.rval().setUndefined(); return true; } setControlText(pControl, szText); - JS_free(ctx, szText); args.rval().setUndefined(); return true; } diff --git a/src/Spidermonkey Engine/Core/JS/JSCore.cpp b/src/Spidermonkey Engine/Core/JS/JSCore.cpp index 15169977..3572aa9f 100644 --- a/src/Spidermonkey Engine/Core/JS/JSCore.cpp +++ b/src/Spidermonkey Engine/Core/JS/JSCore.cpp @@ -33,12 +33,11 @@ bool my_stringToEUC(JSContext* ctx, JS::CallArgs& args) { return true; } - char* szText = JS_EncodeString(ctx, args[0].toString()); + StringWrap szText(ctx, args[0]); if (!szText) { THROW_ERROR(ctx, "failed to encode string"); } - std::string ansi = UTF8ToANSI(szText); - JS_free(ctx, szText); + std::string ansi = UTF8ToANSI(szText.c_str()); args.rval().setString(JS_NewStringCopyN(ctx, ansi.c_str(), ansi.length())); return true; } @@ -49,13 +48,12 @@ bool my_print(JSContext* ctx, JS::CallArgs& args) { if (i != 0) { ss << " "; } - char* str = JS_EncodeString(ctx, JS::ToString(ctx, args[i])); + StringWrap str(ctx, JS::ToString(ctx, args[i])); if (!str) { JS_ReportErrorASCII(ctx, "failed to encode string"); return false; } - ss << str; - JS_free(ctx, str); + ss << str.c_str(); } std::string finalstr = ss.str(); Print(finalstr.c_str()); @@ -82,13 +80,12 @@ bool my_load(JSContext* ctx, JS::CallArgs& args) { return false; } ThreadState* ts = static_cast(JS_GetContextPrivate(ctx)); - char* file = JS_EncodeString(ctx, args[0].toString()); + StringWrap file(ctx, args[0]); if (!file) { THROW_ERROR(ctx, "failed to encode string"); } - if (strlen(file) > (_MAX_FNAME + _MAX_PATH - strlen(Vars.szScriptPath))) { - JS_free(ctx, file); + if (file.length() > (_MAX_FNAME + _MAX_PATH - strlen(Vars.szScriptPath))) { JS_ReportErrorASCII(ctx, "File name too long!"); return false; } @@ -98,7 +95,7 @@ bool my_load(JSContext* ctx, JS::CallArgs& args) { scriptState = (ClientState() == ClientStateInGame ? kScriptModeGame : kScriptModeMenu); char buf[_MAX_PATH + _MAX_FNAME]; - sprintf_s(buf, _countof(buf), "%s\\%s", Vars.szScriptPath, file); + sprintf_s(buf, _countof(buf), "%s\\%s", Vars.szScriptPath, file.c_str()); StringReplace(buf, '/', '\\', _countof(buf)); // JSAutoStructuredCloneBuffer** autoBuffer = new JSAutoStructuredCloneBuffer*[argc - 1]; @@ -112,9 +109,8 @@ bool my_load(JSContext* ctx, JS::CallArgs& args) { newScript->Start(); } else { // TODO: Should this actually be there? No notification is bad, but do we want this? maybe throw an exception? - Print("File \"%s\" not found.", file); + Print("File \"%s\" not found.", file.c_str()); } - JS_free(ctx, file); args.rval().setUndefined(); return true; } @@ -124,20 +120,18 @@ bool my_include(JSContext* ctx, JS::CallArgs& args) { return false; } ThreadState* ts = static_cast(JS_GetContextPrivate(ctx)); - char* file = JS_EncodeString(ctx, args[0].toString()); + StringWrap file(ctx, args[0]); if (!file) { THROW_ERROR(ctx, "failed to encode string"); } - if (strlen(file) > (_MAX_FNAME + _MAX_PATH - strlen(Vars.szScriptPath) - 6)) { - JS_free(ctx, file); + if (file.length() > (_MAX_FNAME + _MAX_PATH - strlen(Vars.szScriptPath) - 6)) { JS_ReportErrorASCII(ctx, "File name too long!"); return false; } char buf[_MAX_PATH + _MAX_FNAME]; - sprintf_s(buf, _countof(buf), "%s\\libs\\%s", Vars.szScriptPath, file); - JS_free(ctx, file); + sprintf_s(buf, _countof(buf), "%s\\libs\\%s", Vars.szScriptPath, file.c_str()); args.rval().setBoolean(false); if (_access(buf, 0) == 0) { @@ -192,20 +186,18 @@ bool my_isIncluded(JSContext* ctx, JS::CallArgs& args) { if (!args.requireAtLeast(ctx, "isIncluded", 1)) { return false; } - char* file = JS_EncodeString(ctx, args[0].toString()); + StringWrap file(ctx, args[0]); if (!file) { THROW_ERROR(ctx, "failed to encode string"); } - if (strlen(file) > (_MAX_FNAME + _MAX_PATH - strlen(Vars.szScriptPath) - 6)) { - JS_free(ctx, file); + if (file.length() > (_MAX_FNAME + _MAX_PATH - strlen(Vars.szScriptPath) - 6)) { JS_ReportErrorASCII(ctx, "File name too long"); return false; } char path[_MAX_FNAME + _MAX_PATH]; - sprintf_s(path, _countof(path), "%s\\libs\\%s", Vars.szScriptPath, file); - JS_free(ctx, file); + sprintf_s(path, _countof(path), "%s\\libs\\%s", Vars.szScriptPath, file.c_str()); ThreadState* ts = static_cast(JS_GetContextPrivate(ctx)); args.rval().setBoolean(ts->script->IsIncluded(path)); return true; @@ -228,12 +220,11 @@ bool my_debugLog(JSContext* ctx, JS::CallArgs& args) { if (i != 0) { ss << " "; } - char* str = JS_EncodeString(ctx, args[i].toString()); + StringWrap str(ctx, JS::ToString(ctx, args[i])); if (!str) { THROW_ERROR(ctx, "failed to encode string"); } - ss << str; - JS_free(ctx, str); + ss << str.c_str(); } std::string finalstr = ss.str(); Log(finalstr.c_str()); @@ -245,23 +236,22 @@ bool my_copy(JSContext* ctx, JS::CallArgs& args) { if (!args.requireAtLeast(ctx, "copy", 1)) { return false; } - char* data = JS_EncodeString(ctx, args[0].toString()); + StringWrap data(ctx, args[0]); if (!data) { THROW_ERROR(ctx, "failed to encode string"); } HGLOBAL hText; char* pText; - hText = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, strlen(data) + 1); + hText = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, data.length() + 1); pText = (char*)GlobalLock(hText); - strcpy_s(pText, strlen(data) + 1, data); + strcpy_s(pText, data.length() + 1, data.c_str()); GlobalUnlock(hText); OpenClipboard(NULL); EmptyClipboard(); SetClipboardData(CF_TEXT, hText); CloseClipboard(); - JS_free(ctx, data); args.rval().setUndefined(); return true; } @@ -344,8 +334,8 @@ bool my_addEventListener(JSContext* ctx, JS::CallArgs& args) { } if (args[0].isString() && JS::IsCallable(args[1].toObjectOrNull())) { - char* evtName = JS_EncodeString(ctx, args[0].toString()); - if (evtName && strlen(evtName)) { + StringWrap evtName(ctx, args[0]); + if (evtName && evtName.length()) { ThreadState* ts = static_cast(JS_GetContextPrivate(ctx)); JS::RootedValue func(ctx, args[1]); ts->script->AddEventListener(evtName, func); @@ -353,7 +343,6 @@ bool my_addEventListener(JSContext* ctx, JS::CallArgs& args) { JS_ReportErrorASCII(ctx, "Event name is invalid!"); return false; } - JS_free(ctx, evtName); } args.rval().setUndefined(); return true; @@ -364,8 +353,8 @@ bool my_removeEventListener(JSContext* ctx, JS::CallArgs& args) { return false; } if (args[0].isString() && JS::IsCallable(args[1].toObjectOrNull())) { - char* evtName = JS_EncodeString(ctx, args[0].toString()); - if (evtName && strlen(evtName)) { + StringWrap evtName(ctx, args[0]); + if (evtName && evtName.length()) { ThreadState* ts = static_cast(JS_GetContextPrivate(ctx)); JS::RootedValue func(ctx, args[1]); ts->script->RemoveEventListener(evtName, func); @@ -373,7 +362,6 @@ bool my_removeEventListener(JSContext* ctx, JS::CallArgs& args) { JS_ReportErrorASCII(ctx, "Event name is invalid!"); return false; } - JS_free(ctx, evtName); } args.rval().setUndefined(); return true; @@ -385,9 +373,8 @@ bool my_clearEvent(JSContext* ctx, JS::CallArgs& args) { } if (args[0].isString()) { ThreadState* ts = static_cast(JS_GetContextPrivate(ctx)); - char* evt = JS_EncodeString(ctx, args[0].toString()); + StringWrap evt(ctx, args[0]); ts->script->RemoveAllListeners(evt); - JS_free(ctx, evt); } args.rval().setUndefined(); return true; @@ -455,14 +442,13 @@ bool my_loadMpq(JSContext* ctx, JS::CallArgs& args) { if (!args.requireAtLeast(ctx, "loadMpq", 1)) { return false; } - char* path = JS_EncodeString(ctx, args[0].toString()); + StringWrap path(ctx, args[0]); if (!path) { THROW_ERROR(ctx, "failed to encode string"); } if (isValidPath(path)) { LoadMPQ(path); } - JS_free(ctx, path); args.rval().setUndefined(); return true; } diff --git a/src/Spidermonkey Engine/Core/JS/JSDirectory.cpp b/src/Spidermonkey Engine/Core/JS/JSDirectory.cpp index 1724513d..e010d6a8 100644 --- a/src/Spidermonkey Engine/Core/JS/JSDirectory.cpp +++ b/src/Spidermonkey Engine/Core/JS/JSDirectory.cpp @@ -20,6 +20,7 @@ #include "D2Helpers.h" // Log #include "Globals.h" #include "File.h" +#include "StringWrap.h" #include @@ -108,24 +109,21 @@ bool DirectoryWrap::Create(JSContext* ctx, JS::CallArgs& args) { if (!args[0].isString()) THROW_ERROR(ctx, "No path passed to dir.create()"); - char* szName = JS_EncodeString(ctx, args[0].toString()); + StringWrap szName(ctx, args[0]); if (!szName) { THROW_ERROR(ctx, "failed to encode string"); } if (!isValidPath(szName)) { - JS_free(ctx, szName); THROW_ERROR(ctx, "invalid path"); } - sprintf_s(path, _MAX_PATH, "%s\\%s\\%s", Vars.szScriptPath, wrap->szName, szName); + sprintf_s(path, _MAX_PATH, "%s\\%s\\%s", Vars.szScriptPath, wrap->szName, szName.c_str()); if (_mkdir(path) == -1 && (errno == ENOENT)) { - JS_ReportErrorASCII(ctx, "Couldn't create directory %s, path %s not found", szName, path); - JS_free(ctx, szName); + JS_ReportErrorASCII(ctx, "Couldn't create directory %s, path %s not found", szName.c_str(), path); return false; } args.rval().setObjectOrNull(DirectoryWrap::Instantiate(ctx, szName)); - JS_free(ctx, szName); return true; } @@ -155,13 +153,12 @@ bool DirectoryWrap::GetFiles(JSContext* ctx, JS::CallArgs& args) { if (args.length() > 1) THROW_ERROR(ctx, "not enough arguments"); - if (args.length() == 1) { - char* szSearch = JS_EncodeString(ctx, args[0].toString()); + if (args.length() == 1 && args[0].isString()) { + StringWrap szSearch(ctx, args[0]); if (!szSearch) { THROW_ERROR(ctx, "failed to encode string"); } - strcpy_s(search, szSearch); - JS_free(ctx, szSearch); + strcpy_s(search, szSearch.c_str()); } long hFile; @@ -206,13 +203,12 @@ bool DirectoryWrap::GetFolders(JSContext* ctx, JS::CallArgs& args) { if (args.length() > 1) THROW_ERROR(ctx, "not enough arguments"); - if (args.length() == 1) { - char* szSearch = JS_EncodeString(ctx, args[0].toString()); + if (args.length() == 1 && args[0].isString()) { + StringWrap szSearch(ctx, args[0]); if (!szSearch) { THROW_ERROR(ctx, "failed to encode string"); } - strcpy_s(search, szSearch); - JS_free(ctx, szSearch); + strcpy_s(search, szSearch.c_str()); } long hFile; @@ -258,31 +254,27 @@ bool DirectoryWrap::OpenDirectory(JSContext* ctx, JS::CallArgs& args) { } char path[_MAX_PATH]; - char* szName = JS_EncodeString(ctx, args[0].toString()); + StringWrap szName(ctx, args[0]); if (!szName) { THROW_ERROR(ctx, "failed to encode string"); } if (!isValidPath(szName)) { - Log("The following path was deemed invalid: %s. (%s, %s)", szName, "JSDirectory.cpp", "my_openDir"); - JS_free(ctx, szName); + Log("The following path was deemed invalid: %s. (%s, %s)", szName.c_str(), "JSDirectory.cpp", "my_openDir"); THROW_ERROR(ctx, "invalid path"); } - sprintf_s(path, _MAX_PATH, "%s\\%s", Vars.szScriptPath, szName); + sprintf_s(path, _MAX_PATH, "%s\\%s", Vars.szScriptPath, szName.c_str()); if ((_mkdir(path) == -1) && (errno == ENOENT)) { - JS_ReportErrorASCII(ctx, "Couldn't get directory %s, path '%s' not found", szName, path); - JS_free(ctx, szName); + JS_ReportErrorASCII(ctx, "Couldn't get directory %s, path '%s' not found", szName.c_str(), path); return false; } JS::RootedObject obj(ctx, DirectoryWrap::Instantiate(ctx, szName)); if (!obj) { - JS_free(ctx, szName); THROW_ERROR(ctx, "failed to instantiate folder"); } args.rval().setObject(*obj); - JS_free(ctx, szName); return true; } diff --git a/src/Spidermonkey Engine/Core/JS/JSFileTools.cpp b/src/Spidermonkey Engine/Core/JS/JSFileTools.cpp index 4019a5db..1d941f76 100644 --- a/src/Spidermonkey Engine/Core/JS/JSFileTools.cpp +++ b/src/Spidermonkey Engine/Core/JS/JSFileTools.cpp @@ -52,18 +52,16 @@ bool FileToolsWrap::Remove(JSContext* ctx, JS::CallArgs& args) { return false; } - char* szFile = JS_EncodeString(ctx, args[0].toString()); + StringWrap szFile(ctx, args[0]); if (!szFile) { THROW_ERROR(ctx, "failed to encode string"); } char fullpath[_MAX_PATH + _MAX_FNAME]; if (getPathRelScript(szFile, _MAX_PATH + _MAX_FNAME, fullpath) == NULL) { - JS_free(ctx, szFile); JS_ReportErrorASCII(ctx, "Invalid file name"); return false; } - JS_free(ctx, szFile); remove(fullpath); args.rval().setUndefined(); @@ -77,8 +75,8 @@ bool FileToolsWrap::Rename(JSContext* ctx, JS::CallArgs& args) { if (args.length() < 2 || !args[1].isString()) THROW_ERROR(ctx, "You must supply a new file name"); - char* szOrig = JS_EncodeString(ctx, args[0].toString()); - char* szNewName = JS_EncodeString(ctx, args[1].toString()); + StringWrap szOrig(ctx, args[0]); + StringWrap szNewName(ctx, args[1]); if (!szOrig || !szNewName) { THROW_ERROR(ctx, "failed to encode string"); } @@ -87,18 +85,12 @@ bool FileToolsWrap::Rename(JSContext* ctx, JS::CallArgs& args) { char pnewName[_MAX_PATH + _MAX_FNAME]; if (getPathRelScript(szOrig, _MAX_PATH + _MAX_FNAME, porig) == NULL) { - JS_free(ctx, szOrig); - JS_free(ctx, szNewName); THROW_ERROR(ctx, "Invalid original file name"); } if (getPathRelScript(szNewName, _MAX_PATH + _MAX_FNAME, pnewName) == NULL) { - JS_free(ctx, szOrig); - JS_free(ctx, szNewName); THROW_ERROR(ctx, "Invalid new file name"); } - JS_free(ctx, szOrig); - JS_free(ctx, szNewName); // hehe, get rid of "ignoring return value" warning rename(porig, pnewName); @@ -113,8 +105,8 @@ bool FileToolsWrap::Copy(JSContext* ctx, JS::CallArgs& args) { if (args.length() < 2 || !args[1].isString()) THROW_ERROR(ctx, "You must supply a new file name"); - char* szOrig = JS_EncodeString(ctx, args[0].toString()); - char* szNewName = JS_EncodeString(ctx, args[1].toString()); + StringWrap szOrig(ctx, args[0]); + StringWrap szNewName(ctx, args[0]); if (!szOrig || !szNewName) { THROW_ERROR(ctx, "failed to encode string"); } @@ -126,21 +118,15 @@ bool FileToolsWrap::Copy(JSContext* ctx, JS::CallArgs& args) { overwrite = args[2].toBoolean(); if (getPathRelScript(szNewName, _MAX_PATH + _MAX_FNAME, pnewName) == NULL) { - JS_free(ctx, szOrig); - JS_free(ctx, szNewName); THROW_ERROR(ctx, "Invalid new file name"); } if (overwrite && _access(pnewName, 0) == 0) { - JS_free(ctx, szOrig); - JS_free(ctx, szNewName); THROW_ERROR(ctx, "permission denied"); } FILE* fptr1 = fileOpenRelScript(szOrig, "r", ctx); FILE* fptr2 = fileOpenRelScript(szNewName, "w", ctx); - JS_free(ctx, szOrig); - JS_free(ctx, szNewName); // If fileOpenRelScript failed, it already reported the error if (fptr1 == NULL || fptr2 == NULL) @@ -181,7 +167,7 @@ bool FileToolsWrap::Exists(JSContext* ctx, JS::CallArgs& args) { if (args.length() < 1 || !args[0].isString()) THROW_ERROR(ctx, "Invalid file name"); - char* szFile = JS_EncodeString(ctx, args[0].toString()); + StringWrap szFile(ctx, args[0]); if (!szFile) { THROW_ERROR(ctx, "failed to encode string"); } @@ -189,10 +175,8 @@ bool FileToolsWrap::Exists(JSContext* ctx, JS::CallArgs& args) { char fullpath[_MAX_PATH + _MAX_FNAME]; if (getPathRelScript(szFile, _MAX_PATH + _MAX_FNAME, fullpath) == NULL) { - JS_free(ctx, szFile); THROW_ERROR(ctx, "Invalid file name"); } - JS_free(ctx, szFile); args.rval().setBoolean(!(_access(fullpath, 0) != 0 && errno == ENOENT)); return true; @@ -202,13 +186,12 @@ bool FileToolsWrap::ReadText(JSContext* ctx, JS::CallArgs& args) { if (args.length() < 1 || !args[0].isString()) THROW_ERROR(ctx, "You must supply a file name"); - char* szFile = JS_EncodeString(ctx, args[0].toString()); + StringWrap szFile(ctx, args[0]); if (!szFile) { THROW_ERROR(ctx, "failed to encode string"); } FILE* fptr = fileOpenRelScript(szFile, "r", ctx); - JS_free(ctx, szFile); // If fileOpenRelScript failed, it already reported the error if (fptr == NULL) @@ -287,14 +270,13 @@ bool FileToolsWrap::AppendText(JSContext* ctx, JS::CallArgs& args) { EnterCriticalSection(&Vars.cFileSection); - char* szFile = JS_EncodeString(ctx, args[0].toString()); + StringWrap szFile(ctx, args[0]); if (!szFile) { LeaveCriticalSection(&Vars.cFileSection); THROW_ERROR(ctx, "failed to encode string"); } FILE* fptr = fileOpenRelScript(szFile, "a+", ctx); - JS_free(ctx, szFile); bool result = true; // If fileOpenRelScript failed, it already reported the error diff --git a/src/Spidermonkey Engine/Core/JS/JSGame.cpp b/src/Spidermonkey Engine/Core/JS/JSGame.cpp index 55d1cd97..b1887596 100644 --- a/src/Spidermonkey Engine/Core/JS/JSGame.cpp +++ b/src/Spidermonkey Engine/Core/JS/JSGame.cpp @@ -23,6 +23,7 @@ #include "JSUnit.h" #include "MapHeader.h" #include "MPQStats.h" +#include "StringWrap.h" bool my_copyUnit(JSContext* ctx, JS::CallArgs& args) { if (!args.requireAtLeast(ctx, "copyUnit", 1)) { @@ -904,7 +905,7 @@ bool my_getSkillByName(JSContext* ctx, JS::CallArgs& args) { return true; } - char* lpszText = JS_EncodeString(ctx, args[0].toString()); + StringWrap lpszText(ctx, args[0]); if (!lpszText || lpszText[0]) { JS_ReportErrorASCII(ctx, "Could not convert string"); return false; @@ -912,14 +913,12 @@ bool my_getSkillByName(JSContext* ctx, JS::CallArgs& args) { D2UnitStrc* player = D2CLIENT_GetPlayerUnit(); if (!player) { - JS_free(ctx, lpszText); args.rval().setUndefined(); return true; } D2SkillStrc* skill = player->GetSkillFromSkillName(lpszText); if (!skill) { - JS_free(ctx, lpszText); args.rval().setUndefined(); return true; } @@ -954,14 +953,13 @@ bool my_getTextSize(JSContext* ctx, JS::CallArgs& args) { return true; } - char* szString = JS_EncodeString(ctx, args[0].toString()); + StringWrap szString(ctx, args[0]); if (!szString) { THROW_ERROR(ctx, "failed to encode string"); } int font = args[1].toInt32(); - POINT r = CalculateTextLen(szString, font); - JS_free(ctx, szString); + POINT r = CalculateTextLen(szString.c_str(), font); JS::RootedValue x(ctx, JS::NumberValue(r.x)); JS::RootedValue y(ctx, JS::NumberValue(r.y)); @@ -1096,12 +1094,11 @@ bool my_playSound(JSContext* ctx, JS::CallArgs& args) { bool my_say(JSContext* ctx, JS::CallArgs& args) { for (uint32_t i = 0; i < args.length(); i++) { - char* str = JS_EncodeString(ctx, args[i].toString()); + StringWrap str(ctx, JS::ToString(ctx, args[i])); if (!str) { THROW_ERROR(ctx, "failed to encode string"); } - Say(L"%S", str); - JS_free(ctx, str); + Say(L"%S", str.c_str()); } args.rval().setBoolean(true); return true; @@ -1220,12 +1217,13 @@ bool my_useSkillPoint(JSContext* ctx, JS::CallArgs& args) { bool my_getBaseStat(JSContext* ctx, JS::CallArgs& args) { if (args.length() > 2) { - char *szStatName = NULL, *szTableName = NULL; + StringWrap szStatName; + StringWrap szTableName; int32_t nBaseStat = 0; int32_t nClassId = 0; int32_t nStat = -1; if (args[0].isString()) { - szTableName = JS_EncodeString(ctx, args[0].toString()); + szTableName = std::move(StringWrap{ctx, args[0]}); if (!szTableName) { JS_ReportErrorASCII(ctx, "Invalid table value"); return false; @@ -1242,23 +1240,19 @@ bool my_getBaseStat(JSContext* ctx, JS::CallArgs& args) { } if (args[2].isString()) { - szStatName = JS_EncodeString(ctx, args[2].toString()); + szStatName = std::move(StringWrap{ctx, args[2]}); if (!szStatName) { - JS_free(ctx, szTableName); JS_ReportErrorASCII(ctx, "Invalid column value"); return false; } } else if (args[2].isInt32()) nStat = args[2].toInt32(); else { - JS_free(ctx, szTableName); JS_ReportErrorASCII(ctx, "Invalid column value"); return false; } JS::RootedValue rval(ctx); FillBaseStat(ctx, &rval, nBaseStat, nClassId, nStat, szTableName, szStatName); - JS_free(ctx, szTableName); - JS_free(ctx, szStatName); args.rval().set(rval); return true; } diff --git a/src/Spidermonkey Engine/Core/JS/JSMenu.cpp b/src/Spidermonkey Engine/Core/JS/JSMenu.cpp index a05b75d2..58f1afd0 100644 --- a/src/Spidermonkey Engine/Core/JS/JSMenu.cpp +++ b/src/Spidermonkey Engine/Core/JS/JSMenu.cpp @@ -4,6 +4,7 @@ #include "JSControl.h" #include "Helpers.h" #include "Engine.h" +#include "StringWrap.h" #include "Profile.h" @@ -22,13 +23,12 @@ bool my_login(JSContext* ctx, JS::CallArgs& args) { } else THROW_ERROR(ctx, "Invalid profile specified!"); } else { - char* szProfile = JS_EncodeString(ctx, args[0].toString()); + StringWrap szProfile(ctx, args[0]); if (!szProfile) { THROW_ERROR(ctx, "failed to encode string"); } - strcpy_s(Vars.szProfile, 256, szProfile); - profile = szProfile; - JS_free(ctx, szProfile); + strcpy_s(Vars.szProfile, 256, szProfile.c_str()); + profile = szProfile.c_str(); } if (profile.empty()) { @@ -53,20 +53,18 @@ bool my_selectChar(JSContext* ctx, JS::CallArgs& args) { if (args.length() != 1 || !args[0].isString()) THROW_ERROR(ctx, "Invalid parameters specified to selectCharacter"); - char* szProfile = JS_EncodeString(ctx, args[0].toString()); + StringWrap szProfile(ctx, args[0]); if (!szProfile) { THROW_ERROR(ctx, "failed to encode string"); } if (!Profile::ProfileExists(szProfile)) { - JS_free(ctx, szProfile); THROW_ERROR(ctx, "Invalid profile specified"); } char charname[24], file[_MAX_FNAME + MAX_PATH]; sprintf_s(file, _countof(file), "%sd2bs.ini", Vars.szPath); - GetPrivateProfileStringA(szProfile, "character", "ERROR", charname, _countof(charname), file); + GetPrivateProfileStringA(szProfile.c_str(), "character", "ERROR", charname, _countof(charname), file); - JS_free(ctx, szProfile); args.rval().setBoolean(OOG_SelectCharacter(charname)); return true; } @@ -79,20 +77,18 @@ bool my_createGame(JSContext* ctx, JS::CallArgs& args) { std::string name, pass; if (args[0].isString()) { - char* jsname = JS_EncodeString(ctx, args[0].toString()); + StringWrap jsname(ctx, args[0]); if (!jsname) { THROW_ERROR(ctx, "failed to encode string"); } - name = jsname; - JS_free(ctx, jsname); + name = jsname.c_str(); } if (args[1].isString()) { - char* jspass = JS_EncodeString(ctx, args[1].toString()); + StringWrap jspass(ctx, args[1]); if (!jspass) { THROW_ERROR(ctx, "failed to encode string"); } - pass = jspass; - JS_free(ctx, jspass); + pass = jspass.c_str(); } int32_t diff = 3; if (args.length() > 2 && args[2].isInt32()) { @@ -117,20 +113,18 @@ bool my_joinGame(JSContext* ctx, JS::CallArgs& args) { std::string name, pass; if (args[0].isString()) { - char* jsname = JS_EncodeString(ctx, args[0].toString()); + StringWrap jsname(ctx, args[0]); if (!jsname) { THROW_ERROR(ctx, "failed to encode string"); } - name = jsname; - JS_free(ctx, jsname); + name = jsname.c_str(); } - if (args[1].toString()) { - char* jspass = JS_EncodeString(ctx, args[1].toString()); + if (args[1].isString()) { + StringWrap jspass(ctx, args[1]); if (!jspass) { THROW_ERROR(ctx, "failed to encode string"); } - pass = jspass; - JS_free(ctx, jspass); + pass = jspass.c_str(); } if (name.length() > 15 || pass.length() > 15) @@ -152,12 +146,11 @@ bool my_addProfile(JSContext* ctx, JS::CallArgs& args) { std::string* vals[] = {&profile, &mode, &gateway, &username, &password, &charname}; for (uint32_t i = 0; i < 6; i++) { - char* tmp = JS_EncodeString(ctx, args[i].toString()); + StringWrap tmp(ctx, args[i]); if (!tmp) { THROW_ERROR(ctx, "failed to encode string"); } - *vals[i] = tmp; - JS_free(ctx, tmp); + *vals[i] = tmp.c_str(); } if (args.length() == 7) { @@ -205,13 +198,12 @@ bool my_createCharacter(JSContext* ctx, JS::CallArgs& args) { if (!args[0].isString() || !args[1].isInt32()) { THROW_ERROR(ctx, "invalid arguments"); } - char* str = JS_EncodeString(ctx, args[0].toString()); + StringWrap str(ctx, args[0]); if (!str) { THROW_ERROR(ctx, "failed to encode string"); } type = args[1].toInt32(); - name = str; - JS_free(ctx, str); + name = str.c_str(); if (args[2].isBoolean()) { hc = args[2].toBoolean(); } diff --git a/src/Spidermonkey Engine/Core/JS/JSParty.cpp b/src/Spidermonkey Engine/Core/JS/JSParty.cpp index f642d5f7..7c6b8f8f 100644 --- a/src/Spidermonkey Engine/Core/JS/JSParty.cpp +++ b/src/Spidermonkey Engine/Core/JS/JSParty.cpp @@ -3,6 +3,7 @@ #include "Bindings.h" #include "D2Helpers.h" // WaitForGameReady #include "JSUnit.h" // JSUnit +#include "StringWrap.h" JSObject* PartyWrap::Instantiate(JSContext* ctx, D2RosterUnitStrc* unit) { JS::RootedObject global(ctx, JS::CurrentGlobalOrNull(ctx)); @@ -201,11 +202,11 @@ bool PartyWrap::GetParty(JSContext* ctx, JS::CallArgs& args) { } if (args.length() == 1) { - char* nPlayerName = nullptr; + StringWrap nPlayerName; uint32_t nPlayerId = NULL; if (args.get(0).toString()) { - nPlayerName = JS_EncodeString(ctx, args[0].toString()); + nPlayerName = std::move(StringWrap{ctx, args[0]}); } else if (args.get(0).isNumber() && !JS::ToUint32(ctx, args[0], &nPlayerId)) { THROW_ERROR(ctx, "Unable to get ID"); } else if (args.get(0).isObject()) { @@ -226,17 +227,13 @@ bool PartyWrap::GetParty(JSContext* ctx, JS::CallArgs& args) { pRosterUnit = pScan; break; } - if (nPlayerName && _stricmp(pScan->szName, nPlayerName) == 0) { + if (nPlayerName && _stricmp(pScan->szName, nPlayerName.c_str()) == 0) { bFound = true; pRosterUnit = pScan; break; } } - if (nPlayerName) { - JS_free(ctx, nPlayerName); - } - if (!bFound) { args.rval().setUndefined(); return true; diff --git a/src/Spidermonkey Engine/Core/JS/JSProfile.cpp b/src/Spidermonkey Engine/Core/JS/JSProfile.cpp index ffa98490..05b6b206 100644 --- a/src/Spidermonkey Engine/Core/JS/JSProfile.cpp +++ b/src/Spidermonkey Engine/Core/JS/JSProfile.cpp @@ -1,6 +1,7 @@ #include "JSProfile.h" #include "Bindings.h" +#include "StringWrap.h" JSObject* ProfileWrap::Instantiate(JSContext* ctx, Profile* prof) { JS::RootedObject global(ctx, JS::CurrentGlobalOrNull(ctx)); @@ -82,57 +83,44 @@ bool ProfileWrap::New(JSContext* ctx, JS::CallArgs& args) { } // Profile(name) - get the named profile else if (args.length() == 1 && args[0].isString()) { - char* str1 = JS_EncodeString(ctx, args[0].toString()); + StringWrap str1(ctx, args[0]); prof = new Profile(str1); - JS_free(ctx, str1); } else if (args.length() > 1 && args[0].isInt32()) { int32_t type = args[0].toInt32(); // Profile(ProfileType.singlePlayer, charname, diff) if (args.length() == 3 && type == PROFILETYPE_SINGLEPLAYER) { - char* str1 = JS_EncodeString(ctx, args[1].toString()); + StringWrap str1(ctx, args[1]); int32_t diff = args[2].toInt32(); prof = new Profile(PROFILETYPE_SINGLEPLAYER, str1, static_cast(diff)); - JS_free(ctx, str1); } // Profile(ProfileType.battleNet, account, pass, charname, gateway) else if (args.length() == 5 && type == PROFILETYPE_BATTLENET) { - char* str1 = JS_EncodeString(ctx, args[1].toString()); - char* str2 = JS_EncodeString(ctx, args[2].toString()); - char* str3 = JS_EncodeString(ctx, args[3].toString()); - char* str4 = JS_EncodeString(ctx, args[4].toString()); + StringWrap str1(ctx, args[1]); + StringWrap str2(ctx, args[2]); + StringWrap str3(ctx, args[3]); + StringWrap str4(ctx, args[4]); prof = new Profile(PROFILETYPE_BATTLENET, str1, str2, str3, str4); - JS_free(ctx, str1); - JS_free(ctx, str2); - JS_free(ctx, str3); - JS_free(ctx, str4); } // Profile(ProfileType.openBattleNet, account, pass, charname, gateway) else if (args.length() == 5 && type == PROFILETYPE_OPEN_BATTLENET) { - char* str1 = JS_EncodeString(ctx, args[1].toString()); - char* str2 = JS_EncodeString(ctx, args[2].toString()); - char* str3 = JS_EncodeString(ctx, args[3].toString()); - char* str4 = JS_EncodeString(ctx, args[4].toString()); + StringWrap str1(ctx, args[1]); + StringWrap str2(ctx, args[2]); + StringWrap str3(ctx, args[3]); + StringWrap str4(ctx, args[4]); prof = new Profile(PROFILETYPE_OPEN_BATTLENET, str1, str2, str3, str4); - JS_free(ctx, str1); - JS_free(ctx, str2); - JS_free(ctx, str3); - JS_free(ctx, str4); } // Profile(ProfileType.tcpIpHost, charname, diff) else if (args.length() == 3 && type == PROFILETYPE_TCPIP_HOST) { - char* str1 = JS_EncodeString(ctx, args[1].toString()); + StringWrap str1(ctx, args[1]); int32_t diff = args[2].toInt32(); prof = new Profile(PROFILETYPE_TCPIP_HOST, str1, static_cast(diff)); - JS_free(ctx, str1); } // Profile(ProfileType.tcpIpJoin, charname, ip) else if (args.length() == 3 && type == PROFILETYPE_TCPIP_JOIN) { - char* str1 = JS_EncodeString(ctx, args[1].toString()); - char* str2 = JS_EncodeString(ctx, args[2].toString()); - prof = new Profile(PROFILETYPE_TCPIP_JOIN, str1, str2); - JS_free(ctx, str1); - JS_free(ctx, str2); + StringWrap str1(ctx, args[1]); + StringWrap str2(ctx, args[2]); + prof = new Profile(PROFILETYPE_TCPIP_JOIN, str1.c_str(), str2.c_str()); } else { THROW_ERROR(ctx, "Invalid parameters."); } diff --git a/src/Spidermonkey Engine/Core/JS/JSScreenHook.cpp b/src/Spidermonkey Engine/Core/JS/JSScreenHook.cpp index 5dc81987..f78dddcd 100644 --- a/src/Spidermonkey Engine/Core/JS/JSScreenHook.cpp +++ b/src/Spidermonkey Engine/Core/JS/JSScreenHook.cpp @@ -6,6 +6,7 @@ #include #include "Bindings.h" +#include "StringWrap.h" JSObject* FrameWrap::Instantiate(JSContext* ctx) { JS::RootedObject global(ctx, JS::CurrentGlobalOrNull(ctx)); @@ -1019,12 +1020,11 @@ bool TextWrap::New(JSContext* ctx, JS::CallArgs& args) { std::wstring szText; if (args.length() > 0 && args[0].isString()) { - char* str = JS_EncodeString(ctx, args[0].toString()); + StringWrap str(ctx, args[0]); if (!str) { THROW_ERROR(ctx, "failed to encode string"); } - szText = AnsiToWide(str); - JS_free(ctx, str); + szText = AnsiToWide(str.c_str()); } if (args.length() > 1 && args[1].isNumber()) JS::ToUint32(ctx, args[1], &x); @@ -1262,13 +1262,12 @@ bool TextWrap::SetText(JSContext* ctx, JS::CallArgs& args) { UNWRAP_OR_RETURN(ctx, &wrap, args.thisv()); TextHook* pTextHook = wrap->pText; if (args[0].isString()) { - char* szText = JS_EncodeString(ctx, args[0].toString()); + StringWrap szText(ctx, args[0]); if (!szText) { THROW_ERROR(ctx, "failed to encode string"); } - std::wstring pText = AnsiToWide(szText); + std::wstring pText = AnsiToWide(szText.c_str()); pTextHook->SetText(pText.c_str()); - JS_free(ctx, szText); } args.rval().setUndefined(); return true; @@ -1354,11 +1353,10 @@ bool ImageWrap::New(JSContext* ctx, JS::CallArgs& args) { bool automap = false; JS::RootedObject click(ctx); JS::RootedObject hover(ctx); - char* szText = nullptr; wchar_t path[_MAX_FNAME + _MAX_PATH]; if (args.length() > 0 && args[0].isString()) { - char* str = JS_EncodeString(ctx, args[0].toString()); + StringWrap str(ctx, args[0]); if (!str) { THROW_ERROR(ctx, "failed to encode string"); } @@ -1378,13 +1376,14 @@ bool ImageWrap::New(JSContext* ctx, JS::CallArgs& args) { if (args.length() > 7 && args[7].isObject() && JS_ObjectIsFunction(ctx, args[7].toObjectOrNull())) hover.set(args[7].toObjectOrNull()); - if (isValidPath(szText)) { - swprintf_s(path, _countof(path), L"%S", szText); - JS_free(ctx, szText); - } else { - JS_free(ctx, szText); - THROW_ERROR(ctx, "Invalid image file path"); - } + // TODO: cba to fix this now + //if (isValidPath(szText)) { + // swprintf_s(path, _countof(path), L"%S", szText); + // JS_free(ctx, szText); + //} else { + // JS_free(ctx, szText); + // THROW_ERROR(ctx, "Invalid image file path"); + //} JS::RootedObject newObject(ctx, JS_NewObjectForConstructor(ctx, &m_class, args)); if (!newObject) { @@ -1470,13 +1469,12 @@ bool ImageWrap::SetLocation(JSContext* ctx, JS::CallArgs& args) { UNWRAP_OR_RETURN(ctx, &wrap, args.thisv()); ImageHook* pImageHook = wrap->pImage; if (args[0].isString()) { - char* szText = JS_EncodeString(ctx, args[0].toString()); + StringWrap szText(ctx, args[0]); if (!szText) { THROW_ERROR(ctx, "failed to encode string"); } - std::wstring pText = AnsiToWide(szText); + std::wstring pText = AnsiToWide(szText.c_str()); pImageHook->SetImage(pText.c_str()); - JS_free(ctx, szText); } args.rval().setUndefined(); return true; diff --git a/src/Spidermonkey Engine/Core/JS/JSScript.cpp b/src/Spidermonkey Engine/Core/JS/JSScript.cpp index 12f715f6..1b64d207 100644 --- a/src/Spidermonkey Engine/Core/JS/JSScript.cpp +++ b/src/Spidermonkey Engine/Core/JS/JSScript.cpp @@ -4,6 +4,7 @@ #include "D2Helpers.h" #include "Localization.h" #include "ScriptEngine.h" +#include "StringWrap.h" struct FindHelper { DWORD tid; @@ -255,12 +256,11 @@ bool ScriptWrap::GetScript(JSContext* ctx, JS::CallArgs& args) { return true; } } else if (args.length() == 1 && args[0].isString()) { - char* name = JS_EncodeString(ctx, args[0].toString()); + StringWrap name(ctx, args[0]); if (!name) { THROW_ERROR(ctx, "failed to encode string"); } char* fname = _strdup(name); - JS_free(ctx, name); StringReplace(fname, '/', '\\', strlen(fname)); FindHelper helper = {0, fname, NULL}; sScriptEngine->ForEachScript(FindScriptByName, &helper); diff --git a/src/Spidermonkey Engine/Core/JS/JSUnit.cpp b/src/Spidermonkey Engine/Core/JS/JSUnit.cpp index 4e007f5b..05515e09 100644 --- a/src/Spidermonkey Engine/Core/JS/JSUnit.cpp +++ b/src/Spidermonkey Engine/Core/JS/JSUnit.cpp @@ -12,6 +12,7 @@ #include "Localization.h" #include "MPQStats.h" #include "Script.h" +#include "StringWrap.h" JSObject* UnitWrap::Instantiate(JSContext* ctx, UnitData* priv, bool isMe) { JS::RootedObject global(ctx, JS::CurrentGlobalOrNull(ctx)); @@ -1009,9 +1010,8 @@ bool UnitWrap::getNext(JSContext* ctx, JS::CallArgs& args) { return true; } if (args.length() > 0 && args[0].isString()) { - char* szText = JS_EncodeString(ctx, args[0].toString()); + StringWrap szText(ctx, args[0]); strcpy_s(lpUnit->szName, 128, szText); - JS_free(ctx, szText); } if (args.length() > 0 && args[0].isNumber() && !args[1].isNull()) @@ -1044,9 +1044,8 @@ bool UnitWrap::getNext(JSContext* ctx, JS::CallArgs& args) { } if (args.length() > 0 && args[0].isString()) { - char* szText = JS_EncodeString(ctx, args[0].toString()); + StringWrap szText(ctx, args[0]); strcpy_s(pmyUnit->szName, 128, szText); - JS_free(ctx, szText); } if (args.length() > 0 && args[0].isNumber() && !args[1].isNull()) @@ -1260,9 +1259,8 @@ bool UnitWrap::getItem(JSContext* ctx, JS::CallArgs& args) { char szName[128] = ""; if (args.length() > 0 && args[0].isString()) { - char* szText = JS_EncodeString(ctx, args[0].toString()); + StringWrap szText(ctx, args[0]); strcpy_s(szName, sizeof(szName), szText); - JS_free(ctx, szText); } if (args.length() > 0 && args[0].isNumber() && !args[0].isNull()) @@ -1669,16 +1667,16 @@ bool UnitWrap::overhead(JSContext* ctx, JS::CallArgs& args) { } if (!args[0].isNullOrUndefined()) { - char* lpszText = JS_EncodeString(ctx, args[0].toString()); + StringWrap lpszText(ctx, args[0]); if (!lpszText) { THROW_ERROR(ctx, "failed to encode string"); } - std::string ansi = UTF8ToANSI(lpszText); + // only God knows why overhead is in ANSI + std::string ansi = UTF8ToANSI(lpszText.c_str()); D2HoverTextStrc* pMsg = D2COMMON_GenerateOverheadMsg(NULL, ansi.c_str(), *D2CLIENT_OverheadTrigger); if (pMsg) { pUnit->pOMsg = pMsg; } - JS_free(ctx, lpszText); } args.rval().setBoolean(true); @@ -2181,9 +2179,8 @@ bool UnitWrap::setSkill(JSContext* ctx, JS::CallArgs& args) { } if (args[0].isString()) { - char* name = JS_EncodeString(ctx, args[0].toString()); + StringWrap name(ctx, args[0]); pSkill = player->GetSkillFromSkillName(name); - JS_free(ctx, name); } else if (args[0].isNumber()) { uint32_t skillId; JS::ToUint32(ctx, args[0], &skillId); @@ -2426,13 +2423,13 @@ bool UnitWrap::getUnit(JSContext* ctx, JS::CallArgs& args) { uint32_t nClassId = (uint32_t)-1; uint32_t nMode = (uint32_t)-1; uint32_t nUnitId = (uint32_t)-1; - char* szName = nullptr; + StringWrap szName; if (args.length() > 0 && args[0].isNumber()) JS::ToInt32(ctx, args[0], &nType); if (args.length() > 1 && args[1].isString()) - szName = JS_EncodeString(ctx, args[1].toString()); + szName = std::move(StringWrap{ctx, args[1]}); if (args.length() > 1 && args[1].isNumber() && !args[1].isNull()) JS::ToUint32(ctx, args[1], &nClassId); @@ -2455,9 +2452,6 @@ bool UnitWrap::getUnit(JSContext* ctx, JS::CallArgs& args) { pUnit = D2UnitStrc::FindUnit(szName ? szName : "", nClassId, nType, nMode, nUnitId); if (!pUnit) { - if (szName) { - JS_free(ctx, szName); - } args.rval().setUndefined(); return true; } @@ -2465,9 +2459,6 @@ bool UnitWrap::getUnit(JSContext* ctx, JS::CallArgs& args) { UnitData* pmyUnit = new UnitData; // leaked? if (!pmyUnit) { - if (szName) { - JS_free(ctx, szName); - } args.rval().setUndefined(); return true; } @@ -2478,9 +2469,6 @@ bool UnitWrap::getUnit(JSContext* ctx, JS::CallArgs& args) { pmyUnit->dwType = pUnit->dwType; pmyUnit->dwUnitId = pUnit->dwUnitId; strcpy_s(pmyUnit->szName, sizeof(pmyUnit->szName), szName ? szName : ""); - if (szName) { - JS_free(ctx, szName); - } JS::RootedObject newObject(ctx, UnitWrap::Instantiate(ctx, pmyUnit)); if (!newObject) { diff --git a/src/Spidermonkey Engine/Core/StringWrap.cc b/src/Spidermonkey Engine/Core/StringWrap.cc index e18303af..16e642e5 100644 --- a/src/Spidermonkey Engine/Core/StringWrap.cc +++ b/src/Spidermonkey Engine/Core/StringWrap.cc @@ -3,6 +3,9 @@ #include #include +StringWrap::StringWrap() : m_str(nullptr), m_length(0) { +} + StringWrap::StringWrap(JSContext* ctx, JSString* str) : m_length(0) { if (!str) { JS_ReportErrorUTF8(ctx, "cannot flatten null string"); diff --git a/src/Spidermonkey Engine/Core/StringWrap.h b/src/Spidermonkey Engine/Core/StringWrap.h index 888cc0e5..256d25f2 100644 --- a/src/Spidermonkey Engine/Core/StringWrap.h +++ b/src/Spidermonkey Engine/Core/StringWrap.h @@ -6,7 +6,7 @@ class StringWrap { public: - StringWrap() = default; + StringWrap(); StringWrap(JSContext* ctx, JSString* str); StringWrap(JSContext* ctx, JS::HandleValue value); diff --git a/src/Spidermonkey Engine/Engine/Script.cpp b/src/Spidermonkey Engine/Engine/Script.cpp index 0f437c59..0fe58708 100644 --- a/src/Spidermonkey Engine/Engine/Script.cpp +++ b/src/Spidermonkey Engine/Engine/Script.cpp @@ -11,6 +11,7 @@ #include "Console.h" #include "JSTimer.h" #include "Bindings.h" +#include "StringWrap.h" #include #include @@ -424,6 +425,7 @@ bool Script::Initialize() { } else { JS::CompileOptions opts(m_context); opts.setFileAndLine("", 1); + opts.setUTF8(true); const char* cmd = "function main() {print('ÿc2D2BSÿc0 :: Started Console'); while (true){delay(10000)};} "; JS_CompileScript(m_context, cmd, strlen(cmd), opts, &m_script); } @@ -492,10 +494,9 @@ void Script::RunMain() { JS_ReportPendingException(m_context); } if (!rval.isUndefined()) { - char* text = JS_EncodeString(m_context, JS::ToString(m_context, rval)); + StringWrap text(m_context, JS::ToString(m_context, rval)); if (text) { - Log(text); - JS_free(m_context, text); + Log(text.c_str()); } } } @@ -732,10 +733,9 @@ bool Script::HandleEvent(std::shared_ptr evt, bool clearList) { if (!JS::Evaluate(m_context, opts, test.data(), test.length(), &rval)) { JS_ReportPendingException(m_context); } else if (!rval.isUndefined()) { - char* text = JS_EncodeString(m_context, JS::ToString(m_context, rval)); + StringWrap text(m_context, JS::ToString(m_context, rval)); if (text) { - Print(text); - JS_free(m_context, text); + Print(text.c_str()); } } } diff --git a/src/Spidermonkey Engine/Engine/js32.cpp b/src/Spidermonkey Engine/Engine/js32.cpp index c4f81820..1662ffc8 100644 --- a/src/Spidermonkey Engine/Engine/js32.cpp +++ b/src/Spidermonkey Engine/Engine/js32.cpp @@ -33,6 +33,7 @@ JSScript* JS_CompileFile(JSContext* ctx, JS::HandleObject /*globalObject*/, std: JS::CompileOptions opts(ctx); opts.setFileAndLine(fileName.c_str(), 1); + opts.setUTF8(true); JS::RootedScript script(ctx); if (!JS_CompileScript(ctx, str.c_str(), str.length(), opts, &script)) { t.close();