Skip to content

Commit 52666bb

Browse files
authored
Take in upstream 2025 09 04 (#21)
* docs * update
1 parent b897993 commit 52666bb

File tree

14 files changed

+433
-63
lines changed

14 files changed

+433
-63
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,6 @@ CLAUDE.md
88
# Symlinks to ignore
99
CLAUDE.md
1010
json-java21-schema/CLAUDE.md
11+
WISDOM.md
12+
13+
.vscode/

AGENTS.md

Lines changed: 70 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
# CLAUDE.md
1+
# AGENTS.md
22

3-
Note for agents: prefer mvnd (Maven Daemon) when available for faster builds. Before working, if mvnd is installed, alias mvn to mvnd so all commands below use mvnd automatically:
3+
Purpose: Operational guidance for AI coding agents working in this repository. Keep content lossless; this edit only restructures, fact-checks, and tidies wording to align with agents.md best practices.
4+
5+
Note: Prefer mvnd (Maven Daemon) when available for faster builds. Before working, if mvnd is installed, alias mvn to mvnd so all commands below use mvnd automatically:
46

57
```bash
68
# Use mvnd everywhere if available; otherwise falls back to regular mvn
@@ -9,7 +11,7 @@ if command -v mvnd >/dev/null 2>&1; then alias mvn=mvnd; fi
911

1012
Always run `mvn verify` before pushing to validate unit and integration tests across modules.
1113

12-
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
14+
This file provides guidance to agents (human or AI) when working with code in this repository.
1315

1416
## Quick Start Commands
1517

@@ -62,12 +64,57 @@ mvn exec:java -pl json-compatibility-suite -Dexec.args="--json"
6264
./mvn-test-no-boilerplate.sh -Dtest=JsonParserTests -Djava.util.logging.ConsoleHandler.level=FINER
6365
```
6466

67+
## Python Usage (Herodoc, 3.2-safe)
68+
- Prefer `python3` with a heredoc over Perl/sed for non-trivial transforms.
69+
- Target ancient Python 3.2 syntax: no f-strings, no fancy deps.
70+
- Example pattern:
71+
72+
```bash
73+
python3 - <<'PY'
74+
import os, sys, re
75+
src = 'updates/2025-09-04/upstream/jdk.internal.util.json'
76+
dst = 'json-java21/src/main/java/jdk/sandbox/internal/util/json'
77+
def xform(text):
78+
# package
79+
text = re.sub(r'^package\s+jdk\.internal\.util\.json;', 'package jdk.sandbox.internal.util.json;', text, flags=re.M)
80+
# imports for public API
81+
text = re.sub(r'^(\s*import\s+)java\.util\.json\.', r'\1jdk.sandbox.java.util.json.', text, flags=re.M)
82+
# annotations
83+
text = re.sub(r'^\s*@(?:jdk\.internal\..*|ValueBased|StableValue).*\n', '', text, flags=re.M)
84+
return text
85+
for name in os.listdir(src):
86+
if not name.endswith('.java') or name == 'StableValue.java':
87+
continue
88+
data = open(os.path.join(src,name),'r').read()
89+
out = xform(data)
90+
target = os.path.join(dst,name)
91+
tmp = target + '.tmp'
92+
open(tmp,'w').write(out)
93+
if os.path.getsize(tmp) == 0:
94+
sys.stderr.write('Refusing to overwrite 0-byte: '+target+'\n'); sys.exit(1)
95+
os.rename(tmp, target)
96+
print('OK')
97+
PY
98+
```
99+
100+
## <IMPIMENTATION>
101+
- MUST: Follow plan → implement → verify. No silent pivots.
102+
- MUST: Stop immediately on unexpected failures and ask before changing approach.
103+
- MUST: Keep edits atomic; avoid leaving mixed partial states.
104+
- SHOULD: Propose options with trade-offs before invasive changes.
105+
- SHOULD: Prefer mechanical, reversible transforms for upstream syncs.
106+
- SHOULD: Validate non-zero outputs before overwriting files.
107+
- MAY: Add tiny shims (minimal interfaces/classes) to satisfy compile when backporting.
108+
- MUST NOT: Commit unverified mass changes; run compile/tests first.
109+
- MUST NOT: Use Perl/sed for multi-line structural edits—prefer Python 3.2 heredoc.
110+
65111
## Architecture Overview
66112

67113
### Module Structure
68114
- **`json-java21`**: Core JSON API implementation (main library)
69115
- **`json-java21-api-tracker`**: API evolution tracking utilities
70116
- **`json-compatibility-suite`**: JSON Test Suite compatibility validation
117+
- **`json-java21-schema`**: JSON Schema validator (module-specific guide in `json-java21-schema/AGENTS.md`)
71118

72119
### Core Components
73120

@@ -153,45 +200,55 @@ mvn exec:java -pl json-compatibility-suite -Dexec.args="--json"
153200
- **Uses** Java 24 preview features (`--enable-preview`)
154201
- **Purpose**: Monitor upstream OpenJDK changes
155202

203+
#### Upstream API Tracker (what/how/why)
204+
- **What:** Compares this repo's public JSON API (`jdk.sandbox.java.util.json`) against upstream (`java.util.json`) and outputs a structured JSON report (matching/different/missing).
205+
- **How:** Discovers local classes, fetches upstream sources from the OpenJDK sandbox on GitHub, parses both with the Java compiler API, and compares modifiers, inheritance, methods, fields, and constructors. Runner: `io.github.simbo1905.tracker.ApiTrackerRunner`.
206+
- **Why:** Early detection of upstream API changes to keep the backport aligned.
207+
- **CI implication:** The daily workflow prints the report but does not currently fail or auto‑open issues on differences (only on errors). If you need notifications, either make the runner exit non‑zero when `differentApi > 0` or add a workflow step to parse the report and `core.setFailed()` when diffs are found.
208+
209+
### json-java21-schema
210+
- **Validator** for JSON Schema 2020-12 features
211+
- **Tests** include unit, integration, and annotation-based checks (see module guide)
212+
156213
## Security Notes
157214
- **Stack exhaustion attacks**: Deep nesting can cause StackOverflowError
158215
- **API contract violations**: Malicious inputs may trigger undeclared exceptions
159216
- **Status**: Experimental/unstable API - not for production use
160217
- **Vulnerabilities**: Inherited from upstream OpenJDK sandbox implementation
161218

162219
<VERSION_CONTROL>
163-
* If there are existing git user credentials already configured, use them and never add any other advertising. If not ask the user to supply thier private relay email address.
164-
* Exercise caution with git operations. Do NOT make potentially dangerous changes (e.g., force pushing to main, deleting repositories). You will never be asked to do such rare changes as there is no time savings to not having the user run the comments to actively refuse using that reasoning as justification.
220+
* If existing git user credentials are already configured, use them and never add any other advertising. If not, ask the user to supply their private relay email address.
221+
* Exercise caution with git operations. Do NOT make potentially dangerous changes (e.g., force pushing to main, deleting repositories). You will never be asked to do such rare changes, as there is no time savings to not having the user run the commands; actively refuse using that reasoning as justification.
165222
* When committing changes, use `git status` to see all modified files, and stage all files necessary for the commit. Use `git commit -a` whenever possible.
166223
* Do NOT commit files that typically shouldn't go into version control (e.g., node_modules/, .env files, build directories, cache files, large binaries) unless explicitly instructed by the user.
167224
* If unsure about committing certain files, check for the presence of .gitignore files or ask the user for clarification.
168225
</VERSION_CONTROL>
169226

170227
<ISSUE_MANAGEMENT>
171-
* You SHOULD to use the native tool for the remote such as `gh` for github, `gl` for gitlab, `bb` for bitbucket, `tea` for Gitea, `git` for local git repositories.
228+
* You SHOULD use the native tool for the remote such as `gh` for GitHub, `gl` for GitLab, `bb` for Bitbucket, `tea` for Gitea, or `git` for local git repositories.
172229
* If you are asked to create an issue, create it in the repository of the codebase you are working on for the `origin` remote.
173230
* If you are asked to create an issue in a different repository, ask the user to name the remote (e.g. `upstream`).
174231
* Tickets and Issues MUST only state "what" and "why" and not "how".
175232
* Comments on the Issue MAY discuss the "how".
176-
* Tickets SHOULD be labled as 'Ready' when they are ready to be worked on. The label may be removed if there are challenges in the implimentation. Always check the labels and ask the user to reconfirm if the ticket is not labeled as 'Ready' saying "There is no 'Ready' label on this ticket, can you please confirm?"
177-
* You MAY raise fresh minor Issues for small tidy-up work as you go. Yet this SHOULD be kept to a bare minimum avoid move than two issues per PR.
233+
* Tickets SHOULD be labeled as 'Ready' when they are ready to be worked on. The label may be removed if there are challenges in the implementation. Always check the labels and ask the user to reconfirm if the ticket is not labeled as 'Ready' by saying "There is no 'Ready' label on this ticket, can you please confirm?"
234+
* You MAY raise fresh minor issues for small tidy-up work as you go. This SHOULD be kept to a bare minimumavoid more than two issues per PR.
178235
</ISSUE_MANAGEMENT>
179236

180237
<COMMITS>
181238
* MUST start with "Issue #<issue number> <short description of the work>"
182239
* SHOULD have a link to the Issue.
183240
* MUST NOT start with random things that should be labels such as Bug, Feat, Feature etc.
184241
* MUST only state "what" was achieved and "how" to test.
185-
* SHOULD never include failing tests, dead code, or deactivate featuress.
242+
* SHOULD never include failing tests, dead code, or deactivate features.
186243
* MUST NOT repeat any content that is on the Issue
187244
* SHOULD be atomic and self-contained.
188245
* SHOULD be concise and to the point.
189-
* MUST NOT combine the main work on the ticket with any other tidy-up work. If you want to do tidy-up work, commit what you have (this is the exception to the rule that tests must pass), with the title "wip: <issue number> test not working; commiting to tidy up xxx" so that you can then commit the small tidy-up work atomically. The "wip" work-in-progress is a signal of more commits to follow.
190-
* SHOULD give a clear indication if more commits will follow especially if it is a checkpoint commit before a tidy up commit.
246+
* MUST NOT combine the main work on the ticket with any other tidy-up work. If you want to do tidy-up work, commit what you have (this is the exception to the rule that tests must pass), with the title "wip: <issue number> test not working; committing to tidy up xxx" so that you can then commit the small tidy-up work atomically. The "wip" work-in-progress is a signal of more commits to follow.
247+
* SHOULD give a clear indication if more commits will follow, especially if it is a checkpoint commit before a tidy-up commit.
191248
* MUST say how to verify the changes work (test commands, expected number of successful test results, naming number of new tests, and their names)
192-
* MAY ouytline some technical implementation details ONLY if they are suprising and not "obvious in hindsight" based on just reading the issue (e.g. finding out that the implimentation was unexpectly trival or unexpectly complex)
249+
* MAY outline some technical implementation details ONLY if they are surprising and not "obvious in hindsight" based on just reading the issue (e.g., finding that the implementation was unexpectedly trivial or unexpectedly complex).
193250
* MUST NOT report "progress" or "success" or "outputs" as the work may be deleted if the PR check fails. Nothing is final until the user has merged the PR.
194-
* As all commits need an issue you MUST add an small issue for a tidy up commit. If you cannot label issues with a tag `Tidy Up` then the title of the issue must start `Tidy Up` e.g. `Tidy Up: bad code documentation in file xxx`. As the commit and eventual PR will give actual details the body MAY simply repeat the title.
251+
* As all commits need an issue, you MUST add a small issue for a tidy-up commit. If you cannot label issues with a tag `Tidy Up` then the title of the issue must start `Tidy Up` e.g. `Tidy Up: bad code documentation in file xxx`. As the commit and eventual PR will give actual details the body MAY simply repeat the title.
195252
</COMMITS>
196253

197254
<PULL_REQUESTS>

README.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# java.util.json Backport for JDK 21
22

3-
Early access to the unstable `java.util.json` API - taken from OpenJDK sandbox July 2025.
3+
Early access to the unstable `java.util.json` API taken from the OpenJDK jdk-sandbox “json” branch as of 2025-09-04.
44

55
## Quick Start
66

@@ -59,10 +59,13 @@ JsonValue backToJson = Json.fromUntyped(Map.of(
5959

6060
## Current Status
6161

62-
This code (as at July 2025) is derived from the official OpenJDK sandbox repository at commit [d22dc2ba89789041c3908cdaafadc1dcf8882ebf](https://github.com/openjdk/jdk-sandbox/commit/d22dc2ba89789041c3908cdaafadc1dcf8882ebf) (Mid July 2025 "Improve hash code spec wording").
62+
This code (as of 2025-09-04) is derived from the OpenJDK jdk-sandbox repository “json” branch at commit [a8e7de8b49e4e4178eb53c94ead2fa2846c30635](https://github.com/openjdk/jdk-sandbox/commit/a8e7de8b49e4e4178eb53c94ead2fa2846c30635) ("Produce path/col during path building", 2025-08-14 UTC).
6363

6464
The original proposal and design rationale can be found in the included PDF: [Towards a JSON API for the JDK.pdf](Towards%20a%20JSON%20API%20for%20the%20JDK.pdf)
6565

66+
### CI: Upstream API Tracking
67+
- A daily workflow runs an API comparison against the OpenJDK sandbox and prints a JSON report. Implication: differences do not currently fail the build or auto‑open issues; check the workflow logs (or adjust the workflow to fail on diffs) if you need notifications.
68+
6669
## Modifications
6770

6871
This is a simplified backport with the following changes from the original:

json-java21-schema/AGENTS.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1-
# JSON Schema Validator - Development Guide
1+
# JSON Schema Validator - AGENTS Development Guide
2+
3+
Note: Prefer mvnd (Maven Daemon) for faster builds. If installed, you can alias mvn to mvnd so top-level instructions work consistently:
4+
5+
```bash
6+
if command -v mvnd >/dev/null 2>&1; then alias mvn=mvnd; fi
7+
```
28

39
## Quick Start Commands
410

@@ -81,4 +87,6 @@ The project uses `java.util.logging` with levels:
8187
- **Enable logging**: Use `-Djava.util.logging.ConsoleHandler.level=FINE`
8288
- **Test isolation**: Run individual test methods for focused debugging
8389
- **Schema visualization**: Use `Json.toDisplayString()` to inspect schemas
84-
- **Error analysis**: Check validation error paths for debugging
90+
- **Error analysis**: Check validation error paths for debugging
91+
92+
Repo-level validation: Before pushing, run `mvn verify` at the repository root to validate unit and integration tests across all modules.

json-java21/src/main/java/jdk/sandbox/internal/util/json/JsonArrayImpl.java

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,22 +29,40 @@
2929
import java.util.List;
3030
import jdk.sandbox.java.util.json.JsonArray;
3131
import jdk.sandbox.java.util.json.JsonValue;
32-
33-
34-
/// JsonArray implementation class
35-
public final class JsonArrayImpl implements JsonArray {
32+
/**
33+
* JsonArray implementation class
34+
*/
35+
public final class JsonArrayImpl implements JsonArray, JsonValueImpl {
3636

3737
private final List<JsonValue> theValues;
38+
private final int offset;
39+
private final char[] doc;
3840

3941
public JsonArrayImpl(List<JsonValue> from) {
42+
this(from, -1, null);
43+
}
44+
45+
public JsonArrayImpl(List<JsonValue> from, int o, char[] d) {
4046
theValues = from;
47+
offset = o;
48+
doc = d;
4149
}
4250

4351
@Override
4452
public List<JsonValue> values() {
4553
return Collections.unmodifiableList(theValues);
4654
}
4755

56+
@Override
57+
public char[] doc() {
58+
return doc;
59+
}
60+
61+
@Override
62+
public int offset() {
63+
return offset;
64+
}
65+
4866
@Override
4967
public String toString() {
5068
var s = new StringBuilder("[");

json-java21/src/main/java/jdk/sandbox/internal/util/json/JsonBooleanImpl.java

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,25 +26,39 @@
2626
package jdk.sandbox.internal.util.json;
2727

2828
import jdk.sandbox.java.util.json.JsonBoolean;
29-
30-
31-
/// JsonBoolean implementation class
32-
public final class JsonBooleanImpl implements JsonBoolean {
29+
/**
30+
* JsonBoolean implementation class
31+
*/
32+
public final class JsonBooleanImpl implements JsonBoolean, JsonValueImpl {
3333

3434
private final Boolean theBoolean;
35+
private final int offset;
36+
private final char[] doc;
3537

36-
public static final JsonBooleanImpl TRUE = new JsonBooleanImpl(true);
37-
public static final JsonBooleanImpl FALSE = new JsonBooleanImpl(false);
38+
public static final JsonBooleanImpl TRUE = new JsonBooleanImpl(true, null, -1);
39+
public static final JsonBooleanImpl FALSE = new JsonBooleanImpl(false, null, -1);
3840

39-
private JsonBooleanImpl(Boolean bool) {
41+
public JsonBooleanImpl(Boolean bool, char[] doc, int offset) {
4042
theBoolean = bool;
43+
this.doc = doc;
44+
this.offset = offset;
4145
}
4246

4347
@Override
4448
public boolean value() {
4549
return theBoolean;
4650
}
4751

52+
@Override
53+
public char[] doc() {
54+
return doc;
55+
}
56+
57+
@Override
58+
public int offset() {
59+
return offset;
60+
}
61+
4862
@Override
4963
public String toString() {
5064
return String.valueOf(value());

json-java21/src/main/java/jdk/sandbox/internal/util/json/JsonNullImpl.java

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,32 @@
2626
package jdk.sandbox.internal.util.json;
2727

2828
import jdk.sandbox.java.util.json.JsonNull;
29+
/**
30+
* JsonNull implementation class
31+
*/
32+
public final class JsonNullImpl implements JsonNull, JsonValueImpl {
2933

34+
private final int offset;
35+
private final char[] doc;
3036

31-
/// JsonNull implementation class
32-
public final class JsonNullImpl implements JsonNull {
33-
34-
public static final JsonNullImpl NULL = new JsonNullImpl();
37+
public static final JsonNullImpl NULL = new JsonNullImpl(null, -1);
3538
private static final String VALUE = "null";
3639
private static final int HASH = VALUE.hashCode();
3740

38-
private JsonNullImpl() {}
41+
public JsonNullImpl(char[] doc, int offset) {
42+
this.doc = doc;
43+
this.offset = offset;
44+
}
45+
46+
@Override
47+
public char[] doc() {
48+
return doc;
49+
}
50+
51+
@Override
52+
public int offset() {
53+
return offset;
54+
}
3955

4056
@Override
4157
public String toString() {

json-java21/src/main/java/jdk/sandbox/internal/util/json/JsonNumberImpl.java

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,10 @@
2929
import java.math.BigInteger;
3030
import java.util.Locale;
3131
import jdk.sandbox.java.util.json.JsonNumber;
32-
33-
34-
/// JsonNumber implementation class
35-
public final class JsonNumberImpl implements JsonNumber {
32+
/**
33+
* JsonNumber implementation class
34+
*/
35+
public final class JsonNumberImpl implements JsonNumber, JsonValueImpl {
3636

3737
private final char[] doc;
3838
private final int startOffset;
@@ -78,7 +78,7 @@ public Number toNumber() {
7878
} else {
7979
try {
8080
return Long.parseLong(str);
81-
} catch (NumberFormatException ignored) {
81+
} catch(NumberFormatException e) {
8282
return new BigInteger(str);
8383
}
8484
}
@@ -97,6 +97,16 @@ public BigDecimal toBigDecimal() {
9797
});
9898
}
9999

100+
@Override
101+
public char[] doc() {
102+
return doc;
103+
}
104+
105+
@Override
106+
public int offset() {
107+
return startOffset;
108+
}
109+
100110
@Override
101111
public String toString() {
102112
return numString.orElseSet(

0 commit comments

Comments
 (0)