Make TextBundleWrapper init nullable and fail on non-UTF-8 text - #25968
Make TextBundleWrapper init nullable and fail on non-UTF-8 text#25968jkmassel wants to merge 6 commits into
Conversation
|
| App Name | WordPress | |
| Configuration | Release-Alpha | |
| Build Number | 34143 | |
| Version | PR #25968 | |
| Bundle ID | org.wordpress.alpha | |
| Commit | 19e22d7 | |
| Installation URL | 5v1r4en5vjg10 |
|
| App Name | Jetpack | |
| Configuration | Release-Alpha | |
| Build Number | 34143 | |
| Version | PR #25968 | |
| Bundle ID | com.jetpack.alpha | |
| Commit | 19e22d7 | |
| Installation URL | 7hrd37n50c240 |
🤖 Build Failure AnalysisThis build has failures. Claude has analyzed them - check the build annotations for details. |
Generated by 🚫 Danger |
Now that the TextBundleWrapper initializer bridges to a throwing Swift initializer, surface its read failures instead of swallowing them with try?. Make TypeBasedExtensionContentExtractor.convert(payload:) throwing and thread the error up through handleTextBundle, handleTextPack, processLocalFile, and URLExtractor.convert. The loadItem completion — which already receives an Error — logs both load and conversion failures and balances the dispatch group via defer.
loadShare now returns a ShareLoadOutcome — the assembled share, the attachments that were skipped, and whether anything usable was extracted. extract() yields (items, failures) per provider, accumulated under a lock since loadItem calls back concurrently. The share and draft extensions act on it: cancel the request when nothing extracted and something errored, show a non-blocking notice on a partial failure, and open the editor as before when the share was merely empty.


Follows the pattern from #25964. Highest real-world risk in the audit: reachable via a user-supplied file through the Share Extension, with a guaranteed crash. It grew from that
TextBundleWrappercrash fix into surfacing any share-extraction failure to the user, instead of swallowing it.Summary
TextBundleWrapper'sinitWithContentsOfURL:options:error:(andinitWithFileWrapper:error:) are declared_NonnullunderNS_ASSUME_NONNULL_BEGIN, butreturn nilon any read failure — an unreadable URL, a missinginfo.json, or a missing text file.textproperty is declarednonnullbut is assigned from[[NSString alloc] initWithData:… encoding:NSUTF8StringEncoding], which isnilon non-UTF-8 bytes — yetreadFromFilewrapper:still returnedYES, so a structurally valid bundle could initialize withtext == nil.ShareExtractorimported the initializer as non-optional and non-throwing, then dereferencedbundleWrapperandbundleWrapper.text. AnilNSStringbridged to non-optionalStringtraps.ShareExtractorcollected whatever loaded and silently dropped the rest, so a failed share opened a blank editor with no signal.Fix — TextBundleWrapper
nullable. Anerror:-parameter initializer with a nullable return bridges to a Swift throwing initializer.text, fail the read (return NOwithTextBundleErrorInvalidFormat) when the result isnil, sotextstays honestlynonnull.fileWrapperForAssetFilename:nullableto match its own doc comment.Fix — surface extraction failures
TypeBasedExtensionContentExtractor.convert(payload:)is nowthrows; the error from the throwingTextBundleWrapperinit propagates uphandleTextBundle→handleTextPack→processLocalFile→URLExtractor.convertto theNSItemProvider.loadItemboundary, where it's logged.extract(...)returns(items, failures)per provider — accumulated under anNSLock, sinceloadItemcalls back concurrently — andloadSharereturns aShareLoadOutcome: the assembled share, the skipped attachments, and whether anything usable was extracted.ShareExtensionAbstractViewController):NSExtensionContext.cancelRequest(withError:), via the existing dismissal path, behind an alert.Test plan
WordPressapp and its embedded Share Extension build (generic iOS Simulator)..textbundle/.textpackimports as before.Adds Share Extension strings under
shareExtension.contentError.*andshareExtension.partialError.*.Part of the Objective-C non-null nullability audit; see #25964.