Skip to content

Swing, SwingX and JavaFX compatibility layers: desktop Java apps as Codename One apps - #5980

Open
shai-almog wants to merge 293 commits into
masterfrom
desktop-compat-layer
Open

shai-almog wants to merge 293 commits into
masterfrom
desktop-compat-layer

Conversation

@shai-almog

Copy link
Copy Markdown
Collaborator

What this adds

An existing Swing or JavaFX project builds as a Codename One application for every target, the way an Android module does with the Android compatibility layer. The sources are imported with cn1:import-desktop-project into common/src/main/desktop and built unmodified.

  • maven/swing-compat: java.awt, Java2D, javax.swing, java.beans, javax.imageio, a SwingX subset and the FlatLaf entry points, written over Codename One components. Authored already relocated, because the JDK owns those package names; applications compile against the JDK's Swing.
  • maven/javafx-compat: the javafx.* subset (scene graph, controls, charts, layout panes, properties and bindings, animation, effects, Canvas), authored under the real names.
  • maven/fxml-compiler: FXML and JavaFX CSS compiled at build time; nothing on a device parses XML or reflects.
  • maven/compat-jdk: the JDK classes a device lacks (streams, java.util.function, java.nio.file, regex, CompletableFuture, java.time gaps and more), shared with the Android layer.
  • maven/build-engine: one composed relocation pass over every layer, generated entry points and registries, records and pattern switches desugared, and the compliance check extended so that unsupported API is a build error reported under its original name and source line.
  • Maven and Gradle plugin wiring, the archetype profile, samples (scripts/desktop-compat-samples), screenshot tests in hellocodenameone, an integration test, a real-port interaction harness (maven/integration-tests/desktop-compat-realport) and a benchmark harness (scripts/desktop-compat-benchmarks).
  • Developer guide chapter docs/developer-guide/Desktop-Interop.asciidoc, with measured size, memory and start-up tables.

Verified locally

  • Unit tests green: compat-jdk 276, swing-compat 731, javafx-compat 496, fxml-compiler 45, build-engine 2561 (3 skipped), Maven plugin 439, Gradle plugin 24.
  • SpotBugs: zero findings in the seven modules that produce a report.
  • Control characters, author and since tags, copyright headers, package-info, cast semantics, build-hint catalog, workflow validation and the markdown doc validator pass.

Not verified / known gaps

  • The new workflows (desktop-compat.yml additions, desktop-compat-benchmarks.yml) have never run on GitHub. Windows is unmeasured; macOS runtime numbers need run-macos-bench.sh.
  • Screenshot goldens for the new DesktopCompat* tests have to be seeded from the first CI run.
  • Native Linux port issues found while measuring, not fixed here yet: window size is fixed at 800x600; clips under a transform cull children of a scaled node (one JavaFX game draws only its grid); images are never freed (an image-per-frame canvas application grows without bound); typed text is not visible in text fields.
  • JavaSE port: Ctrl/Alt/Meta key combinations do not reach the application, so accelerators and mnemonics are inert.
  • The cloud builder needs a companion change before cloud builds pick the layers up.

🤖 Generated with Claude Code

shai-almog and others added 30 commits October 8, 2026 20:11
…ides columns

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…lifecycle and input events

Node, Parent, Group, Region and Pane with one lazily created Codename One
peer per node, the JavaFX layout pass pushing bounds into the peers in
device pixels, capture and bubble dispatch of pointer and key input,
focus, hover and pressed state, the stage hosts (form, window, dialog),
Application, Platform and FxLifecycle, the styling hooks, and the first
controls (Control, Labeled, ButtonBase, Button, Label).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ene graph to zero SpotBugs findings

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
HBox, VBox, BorderPane, StackPane, GridPane (with ColumnConstraints,
RowConstraints and ConstraintsBase), FlowPane, TilePane and AnchorPane,
with the per child constraints, grow and shrink distribution, margins,
spans, percentages, wrapping and anchors, and the style hooks the
styling contract promises for them. LayoutPanesTest holds each pane to
child bounds worked out by hand from the documented layout rules.

Region gains a package-private way to position a child inside a margin
without resizing it, which BorderPane needs for its edges.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ab panes

TextInputControl, TextField, PasswordField, TextArea, CheckBox, ToggleButton, RadioButton, Toggle, ToggleGroup, Hyperlink, Separator, Slider, ProgressIndicator, ProgressBar, ScrollPane, SplitPane, TabPane, Tab, SelectionModel, SingleSelectionModel and IndexRange, each over the matching Codename One component where one exists. The scroll, split and tab panes are built from scene-graph regions so their content stays a real descendant.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
javafx.animation: Animation, Timeline, KeyFrame, KeyValue, Interpolator,
AnimationTimer, Transition and the pause, fade, translate, scale, rotate,
sequential and parallel transitions, all driven by one frame clock
(runtime.FrameClock) that registers with the form on screen only while
something runs and has a manual mode for tests.

javafx.concurrent: Worker, WorkerStateEvent, Task and Service. Codename
One has no java.util.concurrent beyond the atomic classes, so a Task is a
Runnable rather than a FutureTask, has no blocking get(), and a Service
has no executor property. The hand-over between threads uses atomics and
Platform.runLater only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Adds javafx.scene.shape (Shape and its subclasses, Path and its
elements, SVGPath with a complete path data parser), javafx.scene.text.Text,
javafx.scene.transform (2D), javafx.scene.canvas and javafx.scene.image.
Everything draws through the one Renderer over FxPath, which gain an
elliptical arc, an elliptical round rectangle and a clip.

Node.getTransforms() is folded into the paint matrix and so into
localToParent, bounds and picking. A canvas keeps a display list that is
replayed on paint and is bounded by clearRect and a cap.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…logs

ListView and TableView show their items in recycled cells over a shared
row flow, with single and multiple row selection. ComboBox, ChoiceBox
and DatePicker sit on the Codename One picker. ContextMenu, Menu and
MenuBar open as popups in a layer over the owner's form, which every
host reaches through SceneInput. Dialog, Alert, TextInputDialog and
ChoiceDialog block through a modal stage. Control gains a context menu
and a tooltip.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…(T) of an absent item as JavaFX has it

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…llapsible pane's toggle action, action accelerators

The click tests no longer wait the click count out; the test base resets it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…odelSupport

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… classes

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…yout

A text area given its text inside a scroll pane overflowed the stack on the
pane's next layout: JViewport.doLayout showed the caret, showing a rectangle
validated the viewport, and the viewport -- still invalid, because it was in
the middle of that very layout -- laid itself out again.

Container.validateTree and JViewport.doLayout no longer start a pass that is
already under way, which covers the same shape in JList.ensureIndexIsVisible,
ScrollDelegate.reveal (JTable, JTree) and JComponent.scrollRectToVisible. The
caret is shown after the widget received the text that moved it, not before,
so an appended log is followed to its last line. JXErrorPane's workaround is
gone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
maven/swing-compat and maven/javafx-compat are relocated into an application
and translated by ParparVM with it, where a failed cast is not an exception.
Both are roots of check-cast-semantics.sh now, and the PR build compiles them
so that --require-all finds them.

The six findings were all in javafx.beans.binding.Bindings: the create*Binding
factories read the result of an erased Callable inside a try that catches
Exception. The result is read as an Object and tested with instanceof.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…l acts once

The two scroll bars are children of the pane. A desktop port gives them room
by policy and overflow and they are dragged with the mouse; a touch device
gives them none and keeps Codename One's own indicator. Corner components are
laid out, and the upper trailing one also beside a column header when there
is no bar below it, which is where SwingX puts the column control.

A MouseWheelListener still receives every wheel event: the window's root peer
listens to Codename One's wheel events, which fire before anything scrolls.
What was wrong is that the content scrolled as well. The Codename One event
is consumed now when a listener received it, or when the pane has wheel
scrolling turned off, and a wheel event passed on to the pane scrolls it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s on

Without line wrap, the default as on the desktop, the area is as wide as its
longest line and a scroll pane scrolls it sideways; with it, the area is as
wide as the viewport. The Codename One widget always breaks at its width, so
it is kept from breaking by being given the width the text needs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…h links

A pane with the content type text/html is drawn by the reader the labels use
instead of as its text with the tags taken out, wrapped at the pane's width.
The reader keeps the href of the link a run of text is in, and a click on one
fires an ACTIVATED HyperlinkEvent.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…pup selects once

An editable combo box is now a container of its ComboBoxEditor's component
and an arrow button that opens a menu of the model's items; Enter in the
field makes the text the selected item and fires comboBoxEdited. The modal
popup of a combo box that is not editable keeps what the user highlights to
itself until it closes, so a dismissed popup fires nothing, and hidePopup
closes it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A desktop application is compiled against a full JDK and names members the
device's classes do not have. The remap now redirects them:

- System properties (user.home, os.name, the separators), getenv, exit,
  lineSeparator; Runtime shutdown hooks, availableProcessors, maxMemory;
  Thread daemon/name/interrupt state, timed join and the default uncaught
  exception handler, which is fed from Display's EDT error handling.
- String.join/matches/format(Locale)/toLowerCase(Locale), the StringBuilder
  and StringBuffer searches, substring and replace, and the Character tests.
- The Integer/Long/Short/Byte/Double/Float/Boolean statics, and Math's
  exact, floor, hyperbolic and rounding functions; the transcendental ones
  go to MathUtil. StrictMath follows Math.
- Whole classes: InvocationTargetException, Thread.UncaughtExceptionHandler,
  java.util.logging Logger and Level over Log, java.util.prefs Preferences
  over the framework's Preferences.

A rule's target may now name a differently called method, which is how
Long.decode and Integer.decode share one class.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…record

The remap step writes the class the project settings name
(codename1.packageName + codename1.mainName): for a Swing application a
DesktopLifecycle whose runMain() calls the recorded main(String[]), for a
JavaFX one an FxLifecycle whose createApplication() constructs the recorded
Application -- its main is never called, and Application.launch does
nothing. The kind is inferred when the record leaves it out, a missing
record falls back to the only candidate, and everything else fails the
build saying what cn1-desktop.properties should hold.

The importer sets the template's main class aside so the generated one can
take its name, and reports third-party libraries as bundled and relocated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
compat_unrelocated searched class files for the bytes of a package name,
and so reported an application that merely holds "javax/swing/JTable" in a
string. It now asks UnrelocatedTypes, a small program in the build engine
that reads each class as the relocation does and reports type references
only. A failure of the check itself no longer reads as a clean directory.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A dependency jar that is part of the application (Maven's compile scope,
Gradle's runtime classpath) and refers to a desktop layer is unpacked into
the classes directory before the relocation, so it is relocated, redirected
and compliance-checked as application code. A provided jar, and one that
names no desktop layer, is left as it was.

What was unpacked is recorded inside the classes: an unchanged jar is left
alone on the next run, a compliance finding names the jar it is in, the
check indexes the relocated copy rather than the jar, and the staged
application no longer merges the jar a second time, unrelocated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ientations

A wrapping list is a grid of equal cells, with the desktop's rules for how
many rows and columns it has, and left and right move the selection by a
column. Cell bounds, hit testing and sizes are checked against the JDK's
own list.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
java.awt.Desktop hands URLs to Display.execute; the toolkit's system
clipboard is the device's, with a minimal java.awt.datatransfer; the
toolkit and ImageIcon read images from a path, a URL or bytes, and an image
that cannot be read has no size instead of failing. javax.imageio.ImageIO
reads into a BufferedImage and writes PNG and JPEG with the device's
encoder, and the Swing relocation now moves javax/imageio/ too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e type selector

The default StyleEngine is now a CSS engine that reads the binary table the
build compiles, and javafx.fxml.FXMLLoader loads documents the build compiled
to Java through a generated dispatcher. Node.getTypeSelector no longer asks a
class for its superclass, which the device library cannot answer.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Compiles FXML documents to Java source and JavaFX style sheets to a binary
table at build time, and generates the dispatcher that reaches a controller's
@FXML members without reflection.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…9dbe

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… themed defaults

setLookAndFeel takes any name or a LookAndFeel object and changes nothing;
getInstalledLookAndFeels, getLookAndFeel, getDefaults and the border,
insets and dimension getters exist. Keys nobody put answer from the theme
for the common endings, and the widgets now read only what the application
put, so a color put under a .background key reaches a table.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@shai-almog

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 364b9f049b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread maven/build-engine/src/main/java/com/codename1/maven/DesktopProjectImporter.java Outdated
Comment thread maven/build-engine/src/main/java/com/codename1/maven/DesktopProjectImporter.java Outdated
Comment thread maven/swing-compat/src/main/java/com/codename1/desktopcompat/java/awt/Color.java Outdated
…pty shapes and reload fixes from review

- The importer decides whether the generated main class name is taken
  from what Kotlin sources declare, not from their file names, and
  accepts @JvmStatic public fun main.
- Stream.sorted(null) throws, as the JDK does.
- Color.decode reads a sign before the radix prefix and rejects values
  past a signed 32-bit int.
- RowFilter compares two numbers of one class as that class does.
- Rectangle2D, Ellipse2D and RoundRectangle2D of negative size have no
  outline.
- An iterator taken before ServiceLoader.reload refuses to go on.
- FlowLayout's wrap test and AffineTransform's Point2D[] overload stay as
  the JDK has them; the reasons are in comments.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@shai-almog

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

stream = g_memory_input_stream_new_from_data(bytes + offset, length, 0);

P1 Badge Validate encoded-image slices before native pointer arithmetic

When Image.createImage(bytes, offset, len) reaches this entry point, neither offset nor offset + length is checked against the Java array length before the pointer is passed to g_memory_input_stream_new_from_data. An invalid but ordinary slice such as an offset near the end with an oversized length therefore makes GdkPixbuf read beyond the managed array instead of producing a Java bounds exception, potentially crashing the native Linux process; validate the complete range before forming bytes + offset.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread maven/compat-jdk/src/main/java/com/codename1/compat/jdk/Delays.java Outdated
…d-files event and map removal fixes from review

- javax.swing.Timer.setDelay reschedules a running timer: the firing
  already due keeps its time and the new period applies after it.
- Delays clamps a delay too long to add to the clock to the end of time
  instead of wrapping into the past and firing at once.
- JFileChooser.setSelectedFiles fires SELECTED_FILES_CHANGED_PROPERTY,
  and the chooser's own selections go through it.
- ObservableMapWrapper's entry iterator reads the removed entry's value
  at removal, so setValue on an earlier entry no longer changes it.
- Linux createImage(byte[], int, int) rejects a range outside the array
  in Java and in the native decoder.
- DefaultListSelectionModel.clearSelection: comment on why an empty
  selection never loops (the -1 end returns at once, as in the JDK).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@shai-almog

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5eea8e1241

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread maven/compat-jdk/src/main/java/com/codename1/compat/jdk/ScheduledPool.java Outdated
…mall-argument sinh/tanh from review

- ScheduledPool: a fixed rate's firings that come during an overrun are
  owed and run late, one after another, as the JDK's scheduleAtFixedRate
  does, instead of being dropped.
- ScheduledPool: work cancelled while it waited for a worker no longer
  starts once it gets one.
- JdkNumbers.sinh/tanh: a Taylor series below |x| = 1, so a small
  argument is no longer cancelled to zero.
- Code comments on four findings that contradict the JDK/OpenJFX:
  newScheduledThreadPool(0) is accepted, PropertyBase.bind compares by
  equals, JProgressBar.setModel fires no "model" event, and
  Interpolator.SPLINE checks the y coordinates too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@shai-almog

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ca2f3a31b9

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread maven/compat-jdk/src/main/java/com/codename1/compat/jdk/JdkDates.java Outdated
Comment thread maven/compat-jdk/src/main/java/com/codename1/compat/jdk/Matcher.java Outdated
Comment thread maven/compat-jdk/src/main/java/com/codename1/compat/jdk/JdkTime.java Outdated
Comment thread maven/compat-jdk/src/main/java/com/codename1/compat/jdk/Executors.java Outdated
Comment thread maven/javafx-compat/src/main/java/javafx/scene/control/RowSelection.java Outdated
Comment thread maven/compat-jdk/src/main/java/com/codename1/compat/jdk/Files.java
shai-almog and others added 3 commits October 14, 2026 11:20
…vokeAll cancellation and in-place row replacement from review

- LocalDate.datesUntil and Matcher.results are lazy streams, as in the
  JDK: limit(1) makes one date / finds one match.
- plusWeeks/minusWeeks (LocalDate, LocalDateTime, ZonedDateTime) throw
  on a week count whose days overflow instead of wrapping.
- invokeAll cancels the unfinished tasks when it exits early; a Future's
  get no longer starts waiting on an interrupted thread.
- RowSelection keeps a row selected when items.set replaces it in place;
  setAll still clears the selection, as in JavaFX.
- Files.move: comment on why a regular file needs no copy fallback
  (File.renameTo already copies and deletes outside its directory).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ain class preflight

The desktop remap writes the application's main class into the classes
directory with its own SourceFile marker, so no source file backs it and
master's preflight reported it as a stale class.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@shai-almog

shai-almog commented Oct 14, 2026 •

Copy link
Copy Markdown
Collaborator Author

Compared 181 screenshots: 181 matched.
✅ Native iOS Metal screenshot tests passed.

Benchmark Results

  • VM Translation Time: 0 seconds
  • Compilation Time: 3160 seconds

Build and Run Timing

Metric Duration
Simulator Boot 79000 ms
Simulator Boot (Run) 0 ms
App Install 14000 ms
App Launch 3000 ms
Test Execution 556000 ms

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 93ms / native 4ms = 23.2x speedup
SIMD float-mul (64K x300) java 73ms / native 6ms = 12.1x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path active (NEON-accelerated)
Base64 CN1 encode 188.000 ms
Base64 CN1 decode 161.000 ms
Base64 native encode 1586.000 ms
Base64 encode ratio (CN1/native) 0.119x (88.1% faster)
Base64 native decode 1406.000 ms
Base64 decode ratio (CN1/native) 0.115x (88.5% faster)
Base64 SIMD encode 109.000 ms
Base64 encode ratio (SIMD/CN1) 0.580x (42.0% faster)
Base64 SIMD decode 66.000 ms
Base64 decode ratio (SIMD/CN1) 0.410x (59.0% faster)
Base64 encode ratio (SIMD/native) 0.069x (93.1% faster)
Base64 decode ratio (SIMD/native) 0.047x (95.3% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 300.000 ms
Image createMask (SIMD on) 4.000 ms
Image createMask ratio (SIMD on/off) 0.013x (98.7% faster)
Image applyMask (SIMD off) 499.000 ms
Image applyMask (SIMD on) 71.000 ms
Image applyMask ratio (SIMD on/off) 0.142x (85.8% faster)
Image modifyAlpha (SIMD off) 536.000 ms
Image modifyAlpha (SIMD on) 55.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.103x (89.7% faster)
Image modifyAlpha removeColor (SIMD off) 167.000 ms
Image modifyAlpha removeColor (SIMD on) 283.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 1.695x (69.5% slower)

@shai-almog

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ae409a7eec

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread maven/compat-jdk/src/main/java/com/codename1/compat/jdk/JdkStrings.java Outdated
Comment thread maven/compat-jdk/src/main/java/com/codename1/compat/jdk/Files.java Outdated
Comment thread maven/compat-jdk/src/main/java/com/codename1/compat/jdk/Executors.java Outdated
Comment thread maven/javafx-compat/src/main/java/javafx/scene/paint/Color.java
Comment thread maven/javafx-compat/src/main/java/javafx/animation/Animation.java Outdated
…ules, intact builders on refused replace, watch goldens

- Files.walk and find discover the tree as it is taken.
- StringBuilder/StringBuffer replace validate before clearing the builder.
- awaitTermination clamps its deadline instead of overflowing.
- Color.web checks the final opacity instead of clamping it and reads
  hsl() as hue/saturation/brightness, both as OpenJFX 23 and 27 do;
  out-of-range components stay clamped, as there.
- Animation checks the delay in the property (zero, unbind, throw) and
  accepts any cycle count, as OpenJFX does.
- Reseed eight watchOS theme goldens for the GeneralPath clip fix.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@shai-almog

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 469a61ed5a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread maven/compat-jdk/src/main/java/com/codename1/compat/jdk/Pattern.java Outdated
Comment thread maven/compat-jdk/src/main/java/com/codename1/compat/jdk/Pattern.java Outdated
Comment thread maven/javafx-compat/src/main/java/javafx/concurrent/Task.java Outdated
Comment thread maven/javafx-compat/src/main/java/javafx/util/Duration.java
Comment thread maven/compat-jdk/src/main/java/com/codename1/compat/jdk/StreamState.java Outdated
…ct Duration arithmetic, last Task update wins, complete close failures, stale FXML output cleared

- Pattern.flags() reports the top-level inline flags the parse ended in,
  as the JDK does; splitAsStream finds pieces on demand.
- Duration toNanos and multipliedBy throw on overflow instead of wrapping,
  borrowing a second for negative values so in-range edges still answer.
- Task coalesces worker updates behind a queued flag rather than a null
  sentinel, so a null between two updates no longer outlives the last.
- Stream close runs every handler past an Error and suppresses later
  failures into the first.
- Maven and Gradle clear generated FXML/CSS output when the JavaFX layer
  leaves the class path.
- Duration.valueOf keeps OpenJFX's number syntax; comment records why.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@shai-almog

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 89cb8679b1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread maven/compat-jdk/src/main/java/com/codename1/compat/jdk/Files.java
Comment thread maven/compat-jdk/src/main/java/com/codename1/compat/jdk/JdkText.java Outdated
Comment thread maven/build-engine/src/main/java/com/codename1/maven/DesktopProjectImporter.java Outdated
…ode points, provided scope on import, constructor references adapted

- java.util.prefs: every use of the Codename One store is serialized; two
  workers saving at once threw inside Storage, which only logged it.
- Files.lines reads as the stream is consumed and closes with it;
  codePoints reads a StringBuilder when the stream runs.
- "".repeat(n) returns at once; an impossible length throws as the JDK does.
- The importer keeps Maven provided and Gradle compileOnly dependencies
  provided instead of bundling them.
- Constructor references to adapted constructors (Locale::new,
  InputStreamReader::new with a Charset) go to static factories.
- The fixed-rate overrun test waits longer and reports what it saw.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@shai-almog

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e4ccd77277

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread maven/compat-jdk/src/main/java/com/codename1/compat/jdk/Preferences.java Outdated
Comment thread maven/compat-jdk/src/main/java/com/codename1/compat/jdk/JdkStrings.java Outdated
Comment thread maven/compat-jdk/src/main/java/com/codename1/compat/jdk/JdkDates.java Outdated
Comment thread maven/compat-jdk/src/main/java/com/codename1/compat/jdk/Files.java Outdated
…sinh/cosh to the top of the range, exact Duration plus/minus/negate, block-wise Files.mismatch

Preference entries are stored under escaped node path and key, so a key
holding a slash or a line break can no longer reach another node's entry
or the key index. Duration's plus and minus methods use exact arithmetic
and throw where the JDK throws; multipliedBy sums its carry first, so
negating the most negative duration answers. MenuItem.fire keeps
OpenJFX's behaviour of firing while disabled (documented in the source).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@shai-almog

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

public int read(char[] cbuf, int off, int len) throws IOException {
ensureOpen();
if (len == 0) {
return 0;
}
int n = 0;
while (n < len) {
int c = read();

P2 Badge Validate reader ranges before consuming input

This overload does not validate cbuf, off, and len before calling read(). With an invalid range such as read(new char[1], 2, 1), it consumes one character and only then throws when assigning to the array, whereas Reader.read must reject the range without changing the stream; the len == 0 fast path also incorrectly accepts null buffers and invalid offsets. Perform the standard null and bounds checks before reading.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

long per = NANOS_PER_SECOND / u.nanos();
return duration(amount / per, amount % per * u.nanos());
}
return Duration.ofSeconds(amount * u.seconds());

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Check overflow when constructing scaled durations

When amount is large and the unit is seconds-based, this multiplication wraps before Duration.ofSeconds receives it. For example, remapped Duration.of(Long.MAX_VALUE, ChronoUnit.DAYS) returns a duration of negative one day because Long.MAX_VALUE * 86400 wraps to -86400, whereas the JDK throws ArithmeticException; use exact multiplication here as in the duration arithmetic methods below.

Useful? React with 👍 / 👎.

Comment on lines +699 to +700
public static ZonedDateTime plusMinutes(ZonedDateTime value, long minutes) {
return plusSeconds(value, minutes * 60);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid overflowing zoned minute arithmetic

For large minute counts, scaling to seconds can wrap to an unrelated value before any range check occurs. In particular, plusMinutes(zdt, 4611686018427387904L) multiplies to zero modulo long and returns the original date-time, while ZonedDateTime.plusMinutes rejects this out-of-range result; decompose the amount or use checked arithmetic. The hour variants immediately below have the same defect.

Useful? React with 👍 / 👎.

Comment on lines +748 to +751
} catch (Throwable t) {
// The stage keeps the failure it was told about.
stage.relay(outcome);
return;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve failures thrown by whenComplete actions

When the source future is already exceptional and the whenComplete action also throws, this catch silently discards the action's failure. The JDK retains the source failure as primary and adds the action failure as a suppressed exception, so diagnostics and code inspecting getSuppressed() lose the second failure here; attach t to the original failure before relaying it.

Useful? React with 👍 / 👎.

Comment on lines +185 to +186
if (braceDepth == 0 && part >= 0) {
throw new IllegalArgumentException("Unmatched braces in the pattern.");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject patterns with unmatched nested braces

This condition reports an unfinished format element only when braceDepth has returned to zero, so a pattern ending inside a nested choice element, such as {0,choice,0#{, is accepted and replaced by an empty parsed format. The JDK throws IllegalArgumentException for that malformed pattern; treating any remaining part >= 0 as unmatched prevents invalid localized messages from silently rendering as blank text.

Useful? React with 👍 / 👎.

Comment on lines +94 to +102
if (old == this) {
if (children.indexOf(n) != children.lastIndexOf(n)) {
throw new IllegalArgumentException("Duplicate child added: " + n);
}
continue;
}
for (Node up = this; up != null; up = up.getParent()) {
if (up == n) {
throw new IllegalArgumentException("A node cannot be its own ancestor: " + n);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Validate children before mutating the scene graph

When a null, duplicate, scene root, or ancestor node is added, these checks run from a list-change listener after ArrayObservableList has already inserted the elements. Throwing therefore leaves the rejected node in children; for example, after catching the exception from pane.getChildren().addAll(child, child), the list still contains the child twice, and a rejected ancestor insertion can leave a cycle that later traversal recurses through. Validate additions before committing them or roll the change back before propagating the exception.

Useful? React with 👍 / 👎.

Comment on lines +143 to +150
if (value == null) {
throw new NullPointerException("The root of a scene must not be null");
}
if (value.getParent() != null) {
throw new IllegalArgumentException(value + " is already inside a scene graph and cannot be a root");
}
if (value.getScene() != null && value.getScene() != Scene.this) {
throw new IllegalArgumentException(value + " is already the root of another scene");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep the previous root when root validation fails

These checks execute from ObjectPropertyBase.invalidated() after root.set() has already stored the new value. Consequently, scene.setRoot(null) throws as expected but leaves scene.getRoot() equal to null while the old root still points at the scene; assigning a parented node similarly leaves the property holding the rejected node. Validate before committing the property value or restore the previous root on failure.

Useful? React with 👍 / 👎.

Comment on lines +381 to +385
for (Scheduled<?> task : live.get()) {
task.disarm();
if (!task.outcome.isDone() && !task.running.get()) {
dropped.add(task);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Release tasks retained after shutdownNow

Every unfinished delayed task remains in live after shutdownNow(): disarming it does not complete outcome, so the whenComplete callback that calls forget() never runs. An executor kept after shutdown therefore retains every queued task and everything captured by its callable indefinitely; this is especially costly for many far-future scheduled jobs. Remove each dropped task from live while preserving the JDK behavior that its future remains incomplete.

Useful? React with 👍 / 👎.

Comment on lines +264 to +266
public void removeNode() throws BackingStoreException {
clear();
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Remove preference subtrees instead of only direct keys

For a non-root node, removeNode() must remove the node and all descendants, but delegating to clear() deletes only keys indexed directly at this path. Thus after node("account/tokens").put("secret", value), calling node("account").removeNode() leaves the secret persisted and retrievable; the removed node also remains usable. On the root this is reversed in a dangerous way: the JDK rejects userRoot().removeNode(), while this implementation clears its keys. Track child nodes and removed state, and refuse removal of the root.

Useful? React with 👍 / 👎.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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