Skip to content

Add display.isValidObject function#908

Open
XeduR wants to merge 1 commit into
coronalabs:masterfrom
XeduR:display.isValidObject-PR#1
Open

Add display.isValidObject function#908
XeduR wants to merge 1 commit into
coronalabs:masterfrom
XeduR:display.isValidObject-PR#1

Conversation

@XeduR
Copy link
Copy Markdown
Contributor

@XeduR XeduR commented Apr 16, 2026

display.isValidObject

Adds a Lua-level API for checking whether a given object is a valid display object that has not been removed.

Current behaviour

Object removal

Calling display.remove( object ) or object:removeSelf() will take until the next frame to finish removing the object. In certain situations, like with collision events, callbacks, etc. it's possible that an object has been removed, but the removal isn't yet finished, which results in a crash if the app tries to access the object.

Example

local rect = display.newRect( 100, 100, 50, 50 )
display.remove( rect )

print( rect.x ) -- output: 100

timer.performWithDelay( 1, function()
    print( rect.x )    -- output: nil
end )

There is currently no reliable way to programmatically checking if a display object has already been removed and developers need to implement their own ad-hoc approaches to test for it.

Image object validity

Solar2D detects when display.newImage or display.newImageRect is given a file that is not an image, or if the image is corrupted or otherwise invalid. Solar2D sends a warning about it to console via CoronaLuaWarning(L, "file '%s' does not contain a valid image", imageName);. Funnily enough, Solar2D does not currently provide a reliable way to check this programmatically.

What this PR does

This PR adds two internal proxy flags to objects, _isRemoved and _isInvalid, that the engine sets at the moment an object is removed or when Solar2D detects an image is invalid upon trying to create it.

This PR also adds a new display.isValidObject( object ) that verifies if a given object is 1) a display object, 2) it has not been removed, and 3) it is not invalid. The function always return a Boolean value, giving developers a reliable way of checking if their display objects are indeed valid or not.

Example

Example

local rect = display.newRect( 100, 100, 50, 50 )
print( display.isValidObject( rect ) ) -- output: true
display.remove( rect )

print( display.isValidObject( rect ) ) -- output: false

timer.performWithDelay( 1, function()
    print( display.isValidObject( rect ) ) -- output: false
end )

Unit tests

The test project runs 18 unit tests that exercise display.isValidObject across all the edge cases: type safety with non-display-object inputs (nil, numbers, strings, tables, functions), removal via display.remove and removeSelf, idempotent double-removal, stage validity, group cascade at various nesting depths, finalize listener timing, same-frame re-parent rescue for both groups and snapshots, every display primitive type (rect, circle, line, polygon, text, container, snapshot, group, capture), widgets, sprites, emitters, snapshot internals (snapshot.group and snapshot.canvas with children), and corrupt/missing images via newImage and newImageRect to verify the _isInvalid flag. Each test checks isValidObject before removal, same-frame after removal, and next-frame after removal, reporting pass/fail.

isValidObject test.zip

- Add display.isValidObject( object ) to init.lua
- Set _isRemoved on removed proxies; cascade to group and snapshot descendants
- Clear _isRemoved on re-insert so same-frame re-parent rescues work
- Make double-remove a no-op instead of an error
- Set _isInvalid on newImage / newImageRect proxies when the bitmap loads as zero bytes
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant