From aa961ff5186b7cbd14df25a8e9f1211ec8219270 Mon Sep 17 00:00:00 2001 From: David Richardson Date: Mon, 10 Aug 2026 20:17:30 -0600 Subject: [PATCH 1/3] Update README to reflect testing branch for the Aristo3 theme --- README.md | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 64d70d3a2..6e971135c 100644 --- a/README.md +++ b/README.md @@ -4,13 +4,32 @@ # Cappuccino: Build Desktop-Class Web Applications > **✨ Project Status: v1.5.0 Baseline & Upcoming v2.0.0 Toolchain** -> -> Cappuccino has been under continuous development since 2008 and is actively maintained. This v1.5.0 release establishes the new resolution-independent Aristo3 theme as the baseline. While Aristo2 remains included, using it requires explicitly setting the theme descriptor. +> +> Cappuccino has been under continuous development since 2008 and is actively maintained. The v1.5.0 release establishes a baseline as we move to the new resolution-independent Aristo3 theme and Go-based toolchain. > For users seeking a complication-free alternative who wish to avoid the Aristo3 work entirely, the legacy-1.4.0 branch provides an unambiguous freeze point. Please note, however, that this legacy branch is not guaranteed to receive any future bug fixes or improvements. > Active development is now focused on the upcoming v2.0.0 release, which will transition the full toolchain to Golang and the platform-native binaries it produces, leaving Node.js and npm behind. +> **🚨 Aristo3 Theme: Community Testing Required** +> +> Aristo3 represents a non-trivial refactoring of AppKit UI classes. While unit tests pass, it must be tested against real-world applications before being merged into `main`. Community members testing against their own applications will accelerate the process. We are not concerned with minor visual breakages or cosmetic regressions at this stage; **the primary concern is structural failures.** +> +> The fully merged state has been pushed to the `aristo3` branch on the canonical repo. +> +> **How to help:** +> 1. Check out the `aristo3` branch: `git fetch origin && git checkout aristo3` +> 2. Build the frameworks and run your existing applications against this branch. +> 3. Open your browser's developer console and watch for: +> - Uncaught `CPException`s or JavaScript errors. +> - Infinite layout loops (browser freezing/tab crashing). +> - Broken responder chains or keyboard event handling. +> - KVO/Binding failures or `valueForThemeAttribute:` resolving to `nil` unexpectedly. +> - View hierarchy corruption (subviews disappearing or failing to clip). +> +> Please leave a 👍 on the [Aristo3 Pull Request](https://github.com/cappuccino/cappuccino/pull/3038) if your apps run without structural failures. If you encounter exceptions or crashes, please leave a comment with the stack trace. **A solid response of thumbs up is required before `main` can be merged. Our intention is to leave no community member behind.** + + ## Why Use Cappuccino? Cappuccino is for building **applications** in the browser — especially complex, data-rich, line-of-business tools where productivity and user experience are paramount. Instead of direct manipulation of HTML, CSS, and the DOM, applications are built using Objective-J, a superset of JavaScript modeled on Objective-C. This gives you a lot of benefits: @@ -93,7 +112,7 @@ Pure JavaScript and Objective-J can be mixed and matched, even in the same file. ## Frequently Asked Questions (FAQ) -**Q: What are the advantages over React or Vue?** +**Q: What are the advantages over React or Vue?** **A:** React and Vue are excellent libraries for building web UIs. Cappuccino is a comprehensive **framework** for building entire **applications**. It provides a fully integrated stack—including a mature UI library, event handling, and data management—designed for large-scale development. Beyond this, Cappuccino provides a more integrated and powerful data-binding layer inspired directly by Cocoa, which dramatically reduces boilerplate code for complex UIs as you can see in this [example code](https://github.com/daboe01/UIBuilder/tree/master/public/Frontend) that uses these features: @@ -103,19 +122,19 @@ Beyond this, Cappuccino provides a more integrated and powerful data-binding lay * **Advanced Filtering with Predicates:** A table displaying thousands of items can be filtered simply by setting a predicate (a declarative filter rule, e.g., `lastName BEGINSWITH 'S'`) on its controller. The UI updates instantly. This eliminates tons of manual state management and filtering logic code. * **Automatic Value Transformation:** Data can be easily formatted for display (e.g., dates, currency, booleans to "Yes/No") directly within the binding itself using value transformers, keeping model data pure and view logic minimal. -**Q: Can Cappuccino be used on Windows/Linux?** +**Q: Can Cappuccino be used on Windows/Linux?** **A:** Yes. The development tools run on Node.js and are platform-independent. Applications can be developed on any OS and deployed on any web server. -**Q: Is Xcode required?** +**Q: Is Xcode required?** **A:** No. Any code editor can be used. Xcode offers optional visual development tools for macOS users, but it is not a requirement. -**Q: Hasn't Apple moved on from Objective-C, making these APIs obsolete?** +**Q: Hasn't Apple moved on from Objective-C, making these APIs obsolete?** **A:** While Swift is Apple's newer language, Objective-C and AppKit remain foundational, actively supported technologies used in many of Apple's flagship applications. Cappuccino leverages the stability and power of this time-tested API design, which is independent of Apple's future product roadmap. -**Q: How can custom HTML, CSS, or JavaScript libraries be integrated?** +**Q: How can custom HTML, CSS, or JavaScript libraries be integrated?** **A:** Cappuccino abstracts away the DOM, but other web technologies can still be integrated. The `CPWebView` control allows arbitrary HTML/CSS/JS content to be embedded. Since Objective-J is a superset of JavaScript, JS libraries can be used and JS functions can be called directly from Objective-J code. -**Q: Does the LGPL license permit closed-source commercial applications?** +**Q: Does the LGPL license permit closed-source commercial applications?** **A:** Yes. The LGPLv2 license allows proprietary, closed-source applications to be built and distributed using Cappuccino. Sharing of source code is only required for any modifications made **to the Cappuccino framework itself**. The application code remains proprietary. --- From 84dab559931965080ef60e99ce8cd483bb2d8cea Mon Sep 17 00:00:00 2001 From: David Richardson Date: Tue, 11 Aug 2026 13:04:05 -0600 Subject: [PATCH 2/3] Fix legacy compiler warnings in CPMapTable Using ES6 destructuring in the `for...of` loop declaration (`var [key, value] of _map.entries()`) causes the legacy Objective-J compiler to emit "uninitialized global variable" warnings for `key` and `value`. This raises concerns about variable scoping and generates unacceptable noise in the CI pipeline. To resolve the warnings, the loop has been restructured to use standard array indexing inside the loop body. A TODO has been added to revert to ES6 destructuring once the legacy compiler is retired. --- Foundation/CPMapTable.j | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/Foundation/CPMapTable.j b/Foundation/CPMapTable.j index 58ebbd861..bc853e78c 100644 --- a/Foundation/CPMapTable.j +++ b/Foundation/CPMapTable.j @@ -105,17 +105,31 @@ // MARK: Creating a Dictionary Representation /*! - Returns a dictionary representation of the map table. - Note: This will only work correctly if all keys are strings. + Returns a dictionary representation of the map table. + Note: This will only work correctly if all keys are strings. - @return A CPDictionary containing the entries of the map table. + @return A CPDictionary containing the entries of the map table. */ - (CPDictionary)dictionaryRepresentation { var dictionary = [CPDictionary dictionary]; - for (var [key, value] of _map.entries()) + // TODO: Revert to ES6 destructuring in the loop declaration once the + // legacy compiler is retired. The legacy parser fails to recognize + // `var [key, value]` as a local scope declaration, causing the variables + // to leak to the global object and emitting false-positive "uninitialized + // global variable" warnings, which is unacceptable for CI hygiene. + // + // for (var [key, value] of _map.entries()) + // { + // [dictionary setObject:value forKey:key]; + // } + + for (var entry of _map.entries()) { + var key = entry[0], + value = entry[1]; + [dictionary setObject:value forKey:key]; } From ce2803f3547c16764cc9d5a51c5f78940f889bcb Mon Sep 17 00:00:00 2001 From: daboe01 Date: Wed, 12 Aug 2026 16:58:12 +0200 Subject: [PATCH 3/3] replace unload event listener with pagehide and add DOM safety checks --- AppKit/Platform/DOM/CPPlatformWindow+DOM.j | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AppKit/Platform/DOM/CPPlatformWindow+DOM.j b/AppKit/Platform/DOM/CPPlatformWindow+DOM.j index 961fb4787..20413329b 100644 --- a/AppKit/Platform/DOM/CPPlatformWindow+DOM.j +++ b/AppKit/Platform/DOM/CPPlatformWindow+DOM.j @@ -481,7 +481,7 @@ _CPPlatformWindowWillCloseNotification = @"_CPPlatformWindowWillCloseNotificatio _DOMWindow.addEventListener("blur", onBlurEventCallback, NO); _DOMWindow.addEventListener("focus", onFocusEventCallback, NO); - _DOMWindow.addEventListener("unload", function() + _DOMWindow.addEventListener("pagehide", function() { _DOMWindow.removeEventListener("unload", arguments.callee, NO);