diff --git a/data/js/commands/testjsbindings.js b/data/js/commands/testjsbindings.js index 239cdeb21..134cde50e 100644 --- a/data/js/commands/testjsbindings.js +++ b/data/js/commands/testjsbindings.js @@ -10,6 +10,7 @@ function CommandRegistration() RegisterCommand( "testjsextended", 2, true ); RegisterCommand( "testjsgc", 8, true ); RegisterCommand( "testjstimer", 8, true ); + RegisterCommand( "testjsinvalidation", 8, true ); RegisterCommand( "testjsarguments", 2, true ); RegisterCommand( "testjserror", 2, true ); RegisterCommand( "testjsall", 2, true ); @@ -302,6 +303,42 @@ function command_TESTJSTIMER( socket, cmdString ) socket.SysMessage( "JavaScript timer/rooting test started. Results will follow in one second." ); } +/** @type { ( socket: Socket, cmdString: string ) => void } */ +function command_TESTJSINVALIDATION( socket, cmdString ) +{ + var failures = []; + var pUser = socket.currentChar; + var testItem = CreateBlankItem( socket, pUser, 1, "wrapper invalidation test", 0x0eed, 0, "ITEM", false ); + + RunBindingTest( failures, "Invalidation setup", function() + { + RequireBinding( ValidateObject( testItem ), "could not create the test item" ); + }); + + if( ValidateObject( testItem )) + { + var testSerial = testItem.serial; + testItem.Delete(); + + RunBindingTest( failures, "Deleted wrapper invalidation", function() + { + RequireBinding( !ValidateObject( testItem ), "deleted item wrapper remained valid" ); + }); + RunBindingTest( failures, "Deleted serial lookup", function() + { + RequireBinding( CalcItemFromSer( testSerial ) == null, "deleted item received a new wrapper" ); + }); + + pUser.ExecuteCommand( "gcollect" ); + RunBindingTest( failures, "Deleted wrapper after GC", function() + { + RequireBinding( !ValidateObject( testItem ), "deleted item wrapper became valid after collection" ); + }); + } + + ReportBindingResults( socket, failures, "JavaScript wrapper-invalidation tests", "All JavaScript wrapper-invalidation tests passed." ); +} + /** @type { ( timerObj: Character | Item, timerID: number ) => void } */ function onTimer( timerObj, timerID ) { diff --git a/source/CJSEngine.cpp b/source/CJSEngine.cpp index 5be0dc4f3..eb5604714 100644 --- a/source/CJSEngine.cpp +++ b/source/CJSEngine.cpp @@ -160,6 +160,11 @@ JSObject *CJSEngine::AcquireObject( IUEEntries iType, void *index, UI08 runTime JSObject *retVal = nullptr; if( index != nullptr && runTime < runtimeList.size() ) { + if(( iType == IUE_CHAR && !ValidateObject( static_cast( index ))) || + ( iType == IUE_ITEM && !ValidateObject( static_cast( index )))) + { + return nullptr; + } retVal = runtimeList[runTime]->AcquireObject( iType, index ); }