scinfu / SwiftSoup

SwiftSoup: Pure Swift HTML Parser, with best of DOM, CSS, and jquery (Supports Linux, iOS, Mac, tvOS, watchOS)
https://scinfu.github.io/SwiftSoup/
MIT License
4.53k stars 346 forks source link

`siblingElements()` returns empty collection when build in release mode #179

Open godbout opened 3 years ago

godbout commented 3 years ago

i've tried removing optimization levels for release for SwiftSoup but doesn't help.

the code:

elements = try document.select(".frontPageWidget tr").first()?.siblingElements()

in both debug and release mode the .first() element is the same and not nil, but only in debug mode i can grab the siblings. in release mode i get nothing.

just a few months old in Swift/Xcode so it's probably on my side. i've built a library that i use along SwiftSoup and it works fine. but i can't figure out that last one. any idea what am i be doing wrong? thanks!

godbout commented 3 years ago

btw using SwiftSoup 2.3.2, Swift 5.3.2, and XCode 12.4.

godbout commented 3 years ago

i've tried removing optimization levels for release for SwiftSoup but doesn't help.

i might believe that i've done that correctly but maybe not. i've made the changes in XCode, but i'm building the release through the command line, with -c release, which might be actually enforcing the optimizations. now that i'm thinking about it it kinda makes sense.

godbout commented 3 years ago

ok so i've compiled the release through Xcode and the issue seems to be with the Swift Compilter — Code Generation. if Optimization Level is set to something else than No Optimization, then siblingElements() returns an empty collection. SPM is enforcing the --options which is why i thought it wasn't this at the first place.

godbout commented 3 years ago

i was able to create a CLI that works from SPM with following command: swift build -c release -Xswiftc -Onone. it passes the No Optimization to the Swift Compiler and siblingElements() works. the CLI is just 1M bigger than expected, but at least it works :))

JaydenIrwin commented 3 years ago

No fix for this yet? This made my app completely unusable on release builds.

It also effects .parent()?.html() which returns empty string on release builds.

Using 2.3.2.

Although I'm still confused because my release builds for an earlier version of my app (last week) worked.

I solved the issue by turning off both code-optimization settings in Xcode.

godbout commented 2 years ago

this has been closed without any hello but the issue is still there. just tested.

scinfu commented 2 years ago

@godbout can you provide an HTML to test it? Thank you

godbout commented 2 years ago

hello. (haha.)

sure, here you go: https://gist.github.com/godbout/2fafd288d4c55d36405f93072975755c

works totally fine until i create an archive that turns the optimizations on. at the end i can still compile something, it's just 1 meg higher than needed but ok. but may be nice to find out what's going on? (put Marvin Gaye's album on...)

scinfu commented 2 years ago

@godbout in this html example what are selecting? document.select(".frontPageWidget tr").first()?.siblingElements()

godbout commented 2 years ago

omg what a DUMBASS i am LMAO. made a mistake in the search query. gist updated.

scinfu commented 2 years ago

@godbout work in release mode. I test in Mac and iOS changing run mode in release and choosing all optimisation levels. This issue appear only with archive?

godbout commented 2 years ago

yeah in my case it fails as soon as it's in RELEASE mode. in DEBUG it finds the items, in RELEASE it doesn't. i'll investigate again though as that's almost a year old issue and i'll post here the results. thanks!

godbout commented 2 years ago

tested here, same. works well in DEBUG without optimizations. when i RELEASE it doesn't work, except if i remove the optimizations. will send more info.

godbout commented 2 years ago

a video showing the issue:

  1. test passes with No Optimization, default for DEBUG. SwiftSoup returns siblingElements properly
  2. test fails with Optimize for Speed, default for RELEASE. SwiftSoup returns properly for first() but fails for the siblingElements()

https://user-images.githubusercontent.com/121373/149382016-429e02ec-cff6-4fb7-bc28-4c9e0b04d044.mp4

godbout commented 2 years ago

the test run in the video is here: https://github.com/godbout/AlfredKat/blob/534c10aaf6c49b48f50c0446777e4508bef3e2b1/Tests/AlfredKatCoreTests/Feature/WorkflowTests.swift#L45 the line failing is here: https://github.com/godbout/AlfredKat/blob/534c10aaf6c49b48f50c0446777e4508bef3e2b1/Sources/AlfredKatCore/Menus/Entrance.swift#L75

maybe it's just me doing something wrong. would not discard this possibility.

scinfu commented 2 years ago

Found the bug, parent Node in SwiftSoup is in weak, weak var parentNode: Node? otherwise we will have a memory leak because parent have an array with all childs.

If you call document.select(".frontPageWidget tr").first()?.siblingElements() more time only he last will have zero elements.

document should be put in a variable and set to nil only after use is finished, if it is freed all the elements not retained in memory will be removed.

I'll think of a solution.

godbout commented 2 years ago

Found the bug, parent Node in SwiftSoup is in weak, weak var parentNode: Node? otherwise we will have a memory leak because parent have an array with all childs.

makes total sense this is a weak var.

If you call document.select(".frontPageWidget tr").first()?.siblingElements() more time only he last will have zero elements.

document should be put in a variable and set to nil only after use is finished, if it is freed all the elements not retained in memory will be removed.

I'll think of a solution.

barely dealing with weak and unowned here so good luck with that one :D

scinfu commented 2 years ago

@godbout issue resolved, try now with 2.3.7

scinfu commented 2 years ago

Nevermind, i make a rollback with 2.3.8. The issue steel live for now

godbout commented 2 years ago

ah, sorry. thought i put this in the email snooze but didn't seem so. my bad.

the fix created other issues?