code-playpad 0.7.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/JAVA-COMPATIBILITY.md +12 -12
  2. package/README.md +104 -14
  3. package/dist/COMPILER-LICENSE-AUDIT.md +104 -0
  4. package/dist/COMPILER-NOTICES.txt +16973 -0
  5. package/dist/THIRD-PARTY-NOTICES.txt +102 -0
  6. package/dist/cdn.js +2 -2
  7. package/dist/compiler-license-manifest.json +198 -0
  8. package/dist/{config-D9w0xYhX.js → config-cwuPIQ48.js} +1 -1
  9. package/dist/cpp-D2TrExLz.js +1 -0
  10. package/dist/cpp-DakNa4ys.js +6 -0
  11. package/dist/dist--J_vhCIU.js +14 -0
  12. package/dist/{dist-B5vq9x6M.js → dist-BIgiGgKu.js} +1 -1
  13. package/dist/dist-BNvM_BAY.js +6 -0
  14. package/dist/{dist-XlpaG2JF.js → dist-BkpKCrXQ.js} +1 -1
  15. package/dist/{dist-BKRQwpg6.js → dist-CJxiVI4a.js} +1 -1
  16. package/dist/dist-CNOK8CHE.js +6 -0
  17. package/dist/dist-D25hs99E.js +10 -0
  18. package/dist/dist-D2igTc4m.js +6 -0
  19. package/dist/{dist-CqpVTRAq.js → dist-D7jBL3Ib.js} +9 -9
  20. package/dist/dist-DXjodKfp.js +6 -0
  21. package/dist/dist-DfFrsBkU.js +8 -0
  22. package/dist/dist-Vr-fb58P.js +12 -0
  23. package/dist/{element-DaStU7U7.js → element-BQWrbSEp.js} +7 -7
  24. package/dist/element.js +1 -1
  25. package/dist/{hints-v5iHTd1l.js → hints-CCMgezw9.js} +1 -1
  26. package/dist/index.d.ts +1 -1
  27. package/dist/index.js +1 -1
  28. package/dist/java-DeBiVPXO.js +6 -0
  29. package/dist/java-Xf1xYcVv.js +1 -0
  30. package/dist/{java-library-bitset.generated-Duwl7F-b.js → java-library-bitset.generated-C3m-nf8F.js} +1 -1
  31. package/dist/{java-library-math.generated-DmUvund7.js → java-library-math.generated-BQwpn8sQ.js} +1 -1
  32. package/dist/{java-library-regex.generated-a8crcad3.js → java-library-regex.generated-ItYSF2aV.js} +1 -1
  33. package/dist/java-library-time.generated-Dl0XA7nZ.js +6 -0
  34. package/dist/java-library.generated-B7ib0gOX.js +6 -0
  35. package/dist/{javascript-CSfl5gbA.js → javascript-CTY3U1Mc.js} +4 -2
  36. package/dist/{javascript-CX-lsX2u.js → javascript-DkarEcEB.js} +4 -2
  37. package/dist/{pyodide-Crdd9em4.js → pyodide-B1U3JD9Z.js} +2 -2
  38. package/dist/{pyodide-CdDlM0du.js → pyodide-BGBI232i.js} +1 -1
  39. package/dist/react.js +1 -1
  40. package/dist/runtime/compiler-assets.d.ts +5 -0
  41. package/dist/runtime/compiler-cache.d.ts +9 -0
  42. package/dist/runtime/config.d.ts +11 -0
  43. package/dist/runtime/cpp/assets.d.ts +6 -0
  44. package/dist/runtime/cpp/project.d.ts +9 -0
  45. package/dist/runtime/cpp/worker.d.ts +1 -0
  46. package/dist/runtime/cpp-worker.generated.d.ts +1 -0
  47. package/dist/runtime/cpp.d.ts +3 -0
  48. package/dist/runtime/java-library-bitset.generated.d.ts +2 -2
  49. package/dist/runtime/java-library-math.generated.d.ts +2 -2
  50. package/dist/runtime/java-library-regex.generated.d.ts +2 -2
  51. package/dist/runtime/java-library-time.generated.d.ts +3 -3
  52. package/dist/runtime/java-library.generated.d.ts +3 -3
  53. package/dist/runtime/java-worker.generated.d.ts +3 -3
  54. package/dist/runtime/worker-runtime.d.ts +1 -0
  55. package/dist/standalone.js +9 -9
  56. package/dist/types.d.ts +13 -1
  57. package/dist/worker-runtime-DfYet3xy.js +9 -0
  58. package/dist/worker-runtime-Dq71SbjR.js +4 -0
  59. package/package.json +18 -6
  60. package/dist/dist-BThnYaQ5.js +0 -12
  61. package/dist/dist-CnC1nMtN.js +0 -6
  62. package/dist/dist-D0FPZcUi.js +0 -8
  63. package/dist/dist-DOsLUKSb.js +0 -10
  64. package/dist/dist-D_qJovVA.js +0 -14
  65. package/dist/dist-DlIO0dzi.js +0 -6
  66. package/dist/dist-DmrP6yta.js +0 -6
  67. package/dist/java-DIL6bxPF.js +0 -1
  68. package/dist/java-DxQWnfHu.js +0 -6
  69. package/dist/java-library-time.generated-mFyqZ0pg.js +0 -6
  70. package/dist/java-library.generated-1yFV284B.js +0 -6
  71. package/dist/worker-runtime-C8pmmgW9.js +0 -4
  72. package/dist/worker-runtime-CNPpMRo1.js +0 -9
@@ -1,9 +1,9 @@
1
- <!-- GENERATED by scripts/sync-java.mjs from java-online-compiler@0.34.1 (f3698375f3087bcbeeae3f7736746cd0c807c689). Do not edit. -->
1
+ <!-- GENERATED by scripts/sync-java.mjs from java-online-compiler@0.39.0 (b00eddf254edc4545e4856c2bf729adfc6d7265c). Do not edit. -->
2
2
 
3
- > This is the compatibility table of the Java engine that code-playpad ships (engine 0.34.1).
3
+ > This is the compatibility table of the Java engine that code-playpad ships (engine 0.39.0).
4
4
  > Paths such as `tests/…`, `SPEC.md` and `docs/…` refer to the engine's source (`java-engine/` in code-playpad's repository), which is not part of the package.
5
5
 
6
- # Compatibility — engine 0.34.1 (Stage A, compact source files, objects, numbers and control flow, collections, lambdas, practice mode, String, format, regex, Math, Random, System, Scanner and IO.readln, inheritance, interfaces, Object, instanceof, enums, records, exceptions, hash order, fixed collections, TreeMap, TreeSet, LinkedList, Stack, lambdas, method references, generic classes and methods, var, annotations, varargs, anonymous classes, streams, subList, local classes, raw types, float, byte and short, pattern matching, sealed classes, BigInteger, BigDecimal, EnumMap, EnumSet, fast I/O, static imports, initializer blocks, text blocks, enum constant bodies, Interface.super, ListIterator, reversed views, access-ordered LinkedHashMap, var lambda parameters, array clone, library subclasses, bridge methods, Vector, Hashtable, StringBuffer, StringJoiner, java.util.regex, outer.new, BitSet, parallel streams, java.time dates, AbstractList, LocalTime, LocalDateTime, Duration)
6
+ # Compatibility — engine 0.39.0 (Stage A, compact source files, objects, numbers and control flow, collections, lambdas, practice mode, String, format, regex, Math, Random, System, Scanner and IO.readln, inheritance, interfaces, Object, instanceof, enums, records, exceptions, hash order, fixed collections, TreeMap, TreeSet, LinkedList, Stack, lambdas, method references, generic classes and methods, var, annotations, varargs, anonymous classes, streams, subList, local classes, raw types, float, byte and short, pattern matching, sealed classes, BigInteger, BigDecimal, EnumMap, EnumSet, fast I/O, static imports, initializer blocks, text blocks, enum constant bodies, Interface.super, ListIterator, reversed views, access-ordered LinkedHashMap, var lambda parameters, array clone, library subclasses, bridge methods, Vector, Hashtable, StringBuffer, StringJoiner, java.util.regex, outer.new, BitSet, parallel streams, java.time dates, AbstractList, LocalTime, LocalDateTime, Duration, Instant, time zones, packages)
7
7
 
8
8
  This document records what the engine accepts, what it rejects, and the evidence that it behaves like Java. Every method of every library class, with its status and the tests that call it, is in docs/feature-manifest.json (`npm run manifest`). The reference is Java SE 25 (SPEC.md §4), and what the engine implements is **a documented subset of Java 25**, not "Java 25".
9
9
 
@@ -41,9 +41,10 @@ Every feature has one status:
41
41
  | **Enums** (JLS 8.9) | Supported with limits | Nested or top-level, with fields, constructors (with the hidden name and ordinal, so NPE messages say `<parameter3>`), methods, static members, and `implements`. `values()` (a new array each time), `valueOf(String)` (`IllegalArgumentException: No enum constant Main.Color.PURPLE`, `NullPointerException: Name is null`, with the enum's own frame), `name()`, `ordinal()`, `compareTo` (by ordinal), `toString()` (overridable), `getDeclaringClass()`, `equals` and `hashCode` (identity). The constants are made when the enum initializes, before its other static fields; an exception there is `ExceptionInInitializerError`. `switch` on an enum, with simple or qualified labels (`case RED`, `case Color.RED`); a switch expression naming every constant needs no `default`; a null selector fails as the JDK's does (`Cannot invoke "Main$Color.ordinal()"`). Enums are Comparable, so they sort and queue in declaration order. javac's errors: `enum classes may not be instantiated`, `modifier public not allowed here`, `name() in E cannot override name() in Enum`. `EnumMap` and `EnumSet` are supported (see *Library*). Constants with a class body (`PLUS { int apply(int a, int b) { return a + b; } }`): each is an anonymous subclass of the enum (`Main$Op$1`, numbered with the anonymous classes of the constants' arguments, before the members'), with its own fields, methods, `super` calls and initializer blocks; `getClass()` is the body's class and `getDeclaringClass()` the enum, also in EnumMap and EnumSet. An enum may leave abstract methods to its constants' bodies. javac's errors: `<anonymous Main$Op$2> is not abstract and does not override abstract method apply(int,int) in Op`, `Op is abstract; cannot be instantiated` (a constant without a body), `non-static variable symbol cannot be referenced from a static context` (the enum's private members are not inherited by a body), `equals(Object) in <anonymous Main$Op$1> cannot override equals(Object) in Enum`. |
42
42
  | **Records** (JLS 8.10) | Supported with limits | Nested or top-level, with components, accessors (generated, or declared: `invalid accessor method in record R`), the canonical constructor (generated, compact `R { ... }` with the fields assigned after its body, or explicit), other constructors (which must call another: `constructor is not canonical, so it must invoke another constructor of class R`), static fields and methods, instance methods, and `implements`. `toString()` (`Point[x=1, y=2]`, components as String.valueOf shows them, with the record's own frame when one fails), `equals` (doubles compared as `Double.compare` does) and `hashCode` (`31 * h + hash(component)`) as the JDK computes them, unless declared. javac's errors: `field declaration must be static`, `cannot assign a value to final variable v`. Generic records (`record Pair<A, B>(A first, B second)`) are supported; so are local records and record patterns (see *Pattern matching*). |
43
43
  | `getClass()`, `X.class` | Supported with limits | A `Class` value per class: `getName()` (`Main$Node`, `[I`), `getSimpleName()` (`Node`, `int[]`), `isInterface()`, `isArray()`, printing as `class Main$Node`, and `==` between classes, as `equals` methods use it. `X.class` is a `Class<X>` (so `new EnumMap<>(Day.class)` infers its key type); `Class<?>` may be declared. The reflection methods are unsupported. |
44
- | Running a file, and programs in several files (JEP 458) | Supported with limits | Behaves like `java <entry>` in source-file mode. The program's other `.java` files (`Session.java` beside `Main.java`) are compiled as the JDK's launcher compiles them: a file when the program first names the class it is named after, so a file nothing names is never compiled, and its errors never reported. Each file has its own imports. A class of the entry file wins over another file's of the same name. Errors and stack traces name each file (`Session.java:2: error: …`, `at Session.describe(Session.java:5)`); where the JDK prints another file's absolute path on disk, the engine prints its name. A file's warnings print again when the program first uses one of its classes, as the launcher's second compilation prints them (a class literal, `Helper.class`, is not counted as a use). Limits: 32 files, 500,000 characters per file and 1,000,000 together. A requested entry that is not among the files fails as `java Missing.java` does (`Error: Could not find or load main class Missing.java`); another file never runs in its place. A `.java` file in a folder (`src/Session.java`, `lib\\Session.java`) is reported by name as not supported, an engine rule for its source sets rather than the JDK's, instead of being left out. Unsupported: `package` declarations, folders, another compact source file with a `main`, and using another file's secondary class (one not named after its file) from outside that file, which the JDK finds only if that file happened to be compiled first. |
44
+ | Running a file, and programs in several files (JEP 458) | Supported with limits | Behaves like `java <entry>` in source-file mode. The program's other `.java` files (`Session.java` beside `Main.java`) are compiled as the JDK's launcher compiles them: a file when the program first names the class it is named after, so a file nothing names is never compiled, and its errors never reported. Each file has its own imports. A class of the entry file wins over another file's of the same name. Errors and stack traces name each file (`Session.java:2: error: …`, `at Session.describe(Session.java:5)`); where the JDK prints another file's absolute path on disk, the engine prints its name. A file's warnings print again when the program first uses one of its classes, as the launcher's second compilation prints them (a class literal, `Helper.class`, is not counted as a use). Limits: 32 files, 500,000 characters per file and 1,000,000 together. A requested entry that is not among the files fails as `java Missing.java` does (`Error: Could not find or load main class Missing.java`); another file never runs in its place. Folders are packages (see the next row); a name with `\\` is reported as not supported. A file first needed by the launch file's declarations (an import, a field's or parameter's type) rather than its code is compiled, as by the launcher, only when the program first loads one of its classes: its code's errors print then, after the output so far, with exit status 2, and a class never loaded is never compiled (ADR 0033). Unsupported: another compact source file with a `main`, and using another file's secondary class (one not named after its file) from outside that file, which the JDK finds only if that file happened to be compiled first. |
45
+ | Packages: `package` declarations, files in folders (ADR 0033) | Supported with limits | `util/Tool.java` declares `package util;` and holds class `util.Tool`, found as the launcher finds it: under the root that the entry's package gives (`app/Main.java` in package `app`: the root is the folder above `app`; `src/Main.java` in no package: `src/`). Single-type, on-demand and static imports of the program's classes and member classes, fully qualified names (`util.MathUtil.square(3)`, `new app.model.Item()`), and JLS 6.4.1's order: the file's classes, single-type imports (the library's too), the package's classes, then on-demand imports, two of which giving a name are javac's `reference to Stack is ambiguous`. Access across packages (JLS 6.6): `Hidden is not public in util; cannot be accessed from outside package`, the same for package-private members and member classes, `describe() has protected access in Shape` (protected members from subclasses, instance ones through the subclass; protected constructors through `super(...)` and anonymous classes), and an inaccessible overload is listed as not applicable. A named package does not see the unnamed one. Binary names everywhere: `getClass().getName()` is `util.Counter`, `getPackageName()` is `util`, stack traces are `at util.MathUtil.boom(MathUtil.java:6)`, uncaught exceptions `errors.AppException: …`. javac's errors for an entry whose folders do not match its package (`end of path to source file does not match its package name app: Main.java`), a package in a compact file, a missing package or class (`package nope does not exist`; `cannot find symbol` with `location: package util`), two imports of one simple name, and an import of the file's own class. Not supported: a file whose package is not its folder's (`util/Tool.java` declaring another package or none; javac reports `bad source file`), and on-demand imports of a class's member types (`import util.Outer.*;`). |
45
46
  | No class / no usable main | Supported | `error: no class declared in source file`; `error: can't find main(String[]) or main() method in class: Main`; `error: can't find class: Main`; for a compact file, `compact source file does not have main method in the form of void main() or void main(String[] args)` |
46
- | `import`: single-type and on-demand | Supported with limits | `import java.util.List;` and `import java.util.*;` for the supported java.util classes (see *Library*); the java.lang ones need no import. A compact source file sees java.util without imports, as Java 25's implicit `import module java.base` gives it. A wrong name gets javac's error: `package java.utill does not exist`, or `cannot find symbol` with `location: package java.util`. Real JDK classes outside the subset (`Instant`, `UUID`, …) are unsupported where they are used. Fully qualified names work without an import, in types and in expressions, for every package the subset has: `java.util.stream.IntStream.range(0, 3)`, `java.util.Map.Entry.comparingByKey()`; `java.time.Instant.now()` is unsupported, not `cannot find symbol`. Classes of java.io, java.math, java.util.function and java.util.stream that the subset has are imported the same way. |
47
+ | `import`: single-type and on-demand | Supported with limits | `import java.util.List;` and `import java.util.*;` for the supported java.util classes (see *Library*); the java.lang ones need no import. A compact source file sees java.util without imports, as Java 25's implicit `import module java.base` gives it. A wrong name gets javac's error: `package java.utill does not exist`, or `cannot find symbol` with `location: package java.util`. Real JDK classes outside the subset (`Clock`, `UUID`, …) are unsupported where they are used. Fully qualified names work without an import, in types and in expressions, for every package the subset has: `java.util.stream.IntStream.range(0, 3)`, `java.util.Map.Entry.comparingByKey()`; `java.time.Clock.systemUTC()` is unsupported, not `cannot find symbol`. Classes of java.io, java.math, java.util.function and java.util.stream that the subset has are imported the same way. |
47
48
  | `import static`: single and on-demand (JLS 7.5.3, 7.5.4) | Supported | Methods and fields of the supported classes: `import static java.lang.Math.*;`, `import static java.lang.System.out;`, `import static java.util.stream.Collectors.*;`, `import static java.util.Map.entry;`, and member types (`import static java.util.Map.Entry;`). A simple name means the program's own local, field or method first, then a single import, then an on-demand one (JLS 6.4.1). A method of the class or an enclosing one, Object's included, hides every import of that name, so `toString(a)` with `Arrays.*` imported is javac's `method toString in class Object cannot be applied`. Overloads from several on-demand imports are resolved together (`sort(int[])` from Arrays, `sort(List)` from Collections). javac's errors: `reference to MAX_VALUE is ambiguous` (fields, and methods equally specific in two classes), `cannot find symbol` with `symbol: static foo`, a missing class or package, `static import only from classes and interfaces`. Imported constants are constants (switch labels). Importing from a JDK class outside the subset (`TimeUnit`) is fine until a name from it is used, which is unsupported. |
48
49
  | Variable-arity methods and constructors (`int... xs`, JLS 8.4.1) | Supported | Chosen in the third phase of overload resolution, as javac chooses (`f(int)` over `f(int...)`, `g(Integer)` over `g(int...)`); the trailing arguments go into a new array, or an array is passed as it is. javac's `varargs parameter must be the last parameter`, `varargs mismatch; …`, and its `[unchecked]` warnings for a parameter type the run cannot check: `Possible heap pollution from parameterized vararg type T` at the declaration and `unchecked generic array creation for varargs parameter of type List<Integer>[]` at the call, unless the method is `@SafeVarargs`. |
49
50
  | **Anonymous classes** (JLS 15.9.5) | Supported with limits | `new Comparator<Integer>() { public int compare(...) { ... } }`, `new Shape("sq") { double area() { ... } }`, `new Iterator<>() { ... }`: extending a class of the program (its constructor's arguments passed on) or a built-in exception, or implementing an interface of the program or the library's `Comparable`, `Comparator`, `Iterable`, `Iterator` and functional interfaces (`Runnable`, `Function`, …), with fields, methods, `@Override`, and the diamond inferred from where the object goes. Named as javac names them (`Main$1`, `Main$Holder$1`, `Main$2$1`, in source order per enclosing class), so stack traces, `getClass().getName()` and `<anonymous Main$1>` in diagnostics match; `getSimpleName()` is empty. They capture effectively final locals of the code around them into javac's `val$x` fields (NPE messages say `"this.val$s"`) and use the enclosing instance's members. javac's errors: `<anonymous Main$1> is not abstract and does not override abstract method …`, `anonymous class implements interface; cannot have arguments`, `cannot inherit from final F`, `local variables referenced from an inner class must be final or effectively final`. Extending an inner class or a library class is unsupported. |
@@ -52,7 +53,7 @@ Every feature has one status:
52
53
  | **Generic classes, interfaces, records and methods** (JLS 8.1.2, 8.4.4) | Supported with limits | `class Node<T>`, `class BST<K extends Comparable<K>, V> implements Iterable<K>`, `interface Fn<A, B>`, `static <T extends Comparable<? super T>> void sort(T[] a)`, `<R> Pair<K, R> withValue(R r)`. Members are seen through the type arguments (`T val` of a `Node<Integer>` is an `Integer`; a type variable's members are its bound's), supertypes are parameterized (`class Strs extends Base<String>`, with the bridge methods javac generates so overriding dispatches), the diamond and generic methods are inferred from the arguments, the target, implicit lambdas' bodies and the parameter a diamond is passed to, and explicit type arguments (`Main.<Integer>repeat(7, 2)`) work. Bounds are checked: `type argument String is not within bounds of type-variable T`, `inference variable T has incompatible bounds` (with javac's `upper bounds`, `lower bounds` and `equality constraints` lines), `cannot infer type arguments for Box<>`. javac's other errors: `non-static type variable T cannot be referenced from a static context`, `generic array creation`, `unexpected type` for `new T()`, `wrong number of type arguments`, `name clash: … have the same erasure`, `cannot use '<>' with non-generic class`. Every diagnostic that names a type variable ends with javac's `where T is a type-variable:` clause. As javac does, a generic member's value is checked against the type it has where it is used, so `Integer[] a = box.items` fails with the JDK's `ClassCastException` when the array is really an `Object[]`. Raw types of the program's generic classes are supported as the library's are (see *Generic types at use sites*). Generic constructors are unsupported. |
53
54
  | Annotations (JLS 9.7) | Supported with limits | `@Override`, `@SuppressWarnings` (a string or an array of them; `"unchecked"` and `"deprecation"` silence those warnings on the class, method, field or local declaration, and `"all"` silences nothing, as in the source launcher), `@FunctionalInterface` (javac's `Unexpected @FunctionalInterface annotation` with its reason), `@SafeVarargs` (javac's `Invalid SafeVarargs annotation` errors) and `@Deprecated` (`since`, `forRemoval`; on a local variable, javac's `[deprecation] … has no effect on this variable declaration` warning), on classes, methods, constructors, fields, parameters and locals. javac's errors: `cannot find symbol` for an unknown annotation, `annotation interface not applicable to this kind of declaration`, `… is not a repeatable annotation interface`, `annotation @SuppressWarnings is missing a default value for the element 'value'`, `incompatible types` for a non-String value. Other annotations (the JDK's, or declared with `@interface`), annotations on types and type arguments, and values other than literals are unsupported. |
54
55
  | Warnings | Supported | javac's `[unchecked]` and `[deprecation]` warnings, as the source launcher prints them: before the program's output on a run, among the errors in source order when compilation fails, and counted (`1 warning`, `2 warnings`) after the errors. |
55
- | `package`, declaring annotation interfaces | Unsupported | |
56
+ | Declaring annotation interfaces | Unsupported | |
56
57
 
57
58
  ## Types and values
58
59
 
@@ -146,7 +147,7 @@ Every feature has one status:
146
147
  | `Collectors` | Supported with limits | `toList`, `toUnmodifiableList`, `toSet`, `toCollection`, `toMap` (two, three or four arguments; a duplicate key is the JDK's `IllegalStateException: Duplicate key a (attempted merging values 1 and 1)`), `groupingBy` (one, two or three arguments), `partitioningBy` (`{false=..., true=...}`), `counting` (a `Long`), `summingInt`/`Long`/`Double`, `averagingInt`/`Long`/`Double`, `summarizingInt`/`Long`/`Double`, `joining` (with a delimiter, prefix and suffix), `mapping`, `filtering`, `flatMapping`, `collectingAndThen`, `reducing`, `minBy`, `maxBy`, `teeing` (`downstream1`, `merger` NPE messages). Maps are filled as the JDK fills them (`groupingBy` through `computeIfAbsent`, so a `HashMap` prints in the JDK's order). `toUnmodifiableSet`/`Map` and the concurrent collectors are unsupported. Type arguments are inferred as javac infers them in the common forms: `collect(Collectors.toList())`, `groupingBy(w -> w.charAt(0), TreeMap::new, Collectors.counting())`, `collectingAndThen(Collectors.toList(), List::size)`. |
147
148
  | `Optional`, `OptionalInt`, `OptionalLong`, `OptionalDouble`, `IntSummaryStatistics` (and `Long`, `Double`) | Supported | `of`, `ofNullable`, `empty`, `get`/`getAsInt`/…, `isPresent`, `isEmpty`, `orElse`, `orElseGet`, `orElseThrow` (with or without a supplier), `ifPresent`, `ifPresentOrElse`, `map`, `flatMap`, `filter`, `or`, `stream`; printed as `Optional[3]`, `Optional.empty`, `OptionalDouble[1.5]`; `NoSuchElementException: No value present`. The statistics' `getCount`, `getSum`, `getMin`, `getMax`, `getAverage`, `accept`, and `IntSummaryStatistics{count=3, sum=80, min=20, average=26.666667, max=30}`. |
148
149
  | `BitSet` | Supported | `set`, `clear`, `flip` (one bit or a range, `set(i, boolean)`), `get` (a bit, or a range as a new BitSet), `length`, `size`, `isEmpty`, `cardinality`, `nextSetBit`, `nextClearBit`, `previousSetBit`, `previousClearBit`, `and`, `or`, `xor`, `andNot`, `intersects`, `clone`, `valueOf(long[])`, `toLongArray`, `stream`, `toString` (`{1, 3, 64}`), `equals` and `hashCode` (the JDK's). Its words as the JDK lays them out: `size()` starts at 64 (or the bits asked for, rounded up to 64), grows to twice as many words or what is needed, and `clone()` trims it unless the size came from the constructor. The JDK's messages: `bitIndex < 0: -1`, `fromIndex: 5 > toIndex: 3`, `nbits < 0: -1`. |
149
- | **`java.time`** (ADRs 0025, 0029) | Supported with limits | `LocalDate` (`of`, `parse`, `ofEpochDay`, `ofYearDay`, `now()` from the browser's clock, the getters, `plus`/`minus` days, weeks, months and years (the day clamped to the month: `2024-01-31` plus a month is `2024-02-29`), `plus(long, TemporalUnit)`, `plus(TemporalAmount)`, `with…`, `atTime`, `atStartOfDay`, `isBefore`/`isAfter`/`isEqual`, `until`, `datesUntil`, `format`, `toString` with the JDK's year signs, `hashCode`, Comparable). `LocalTime` (`of`, `ofSecondOfDay`, `ofNanoOfDay`, `parse`, `now()`, `MIN`/`MAX`/`MIDNIGHT`/`NOON`, the getters, `plus`/`minus` hours to nanoseconds around the clock, `with…`, `truncatedTo`, `until`, `atDate`, `toSecondOfDay`, `toNanoOfDay`, `format`, `toString` as the JDK's: `09:05`, `01:02:03.400`, `01:02:03.000000007`). `LocalDateTime` (`of` with all its overloads, `parse`, `now()`, the date's and the time's getters and `with…`, `plus`/`minus` from years to nanoseconds with the days carried, `until` that leaves out an incomplete last day, `truncatedTo`, `toLocalDate`/`toLocalTime`, `format`, `2024-01-31T22:30`). `Duration` (`of…`, `between` two times or date-times, `parse`, `plus`/`minus`, `multipliedBy`, `dividedBy`, `negated`, `abs`, `truncatedTo`, `to…` and `to…Part`, `PT2H15M` and `PT-1M-29.5S`, long overflow as the JDK's `ArithmeticException`). `Period` (`between` with the JDK's borrow, `of…`, the getters, `normalized`, `multipliedBy`, `P1Y2M3D`), `DayOfWeek` and `Month` (`of`, `getValue`, `plus`, `minus`, `length`), `ChronoUnit` (`between` for any of the three types; a unit a type does not have is the JDK's `UnsupportedTemporalTypeException: Unsupported unit: Hours`), and `DateTimeFormatter` (`ofPattern` with the letters `y u M L d D E H h k K m s S n a` and quoted text, `ISO_LOCAL_DATE`, `ISO_LOCAL_TIME`, `ISO_LOCAL_DATE_TIME`). The parameter types are the JDK's interfaces (`Temporal`, `TemporalAmount`, `TemporalUnit`, `TemporalAccessor`), which a program can name. Mixing types works as on the JDK: `Duration.between(time, dateTime)` takes the date-time's time, the other way round is `Unable to obtain LocalDateTime from TemporalAccessor`, and `date.plus(duration)` is `Unsupported unit: Seconds`. Parsing resolves as the JDK's: an `ofPattern` formatter clamps `31/04` to April 30, the ISO ones reject `2024-02-30`, `h` needs `a`; the JDK's `DateTimeException` and `DateTimeParseException` messages, with the cause, and helpful `NullPointerException` messages. A switch on `DayOfWeek`, `Month`, `ChronoUnit` or `RoundingMode` takes their constants as labels. `now()` reads the clock to the millisecond (the JDK's to the microsecond). `Instant`, time zones and offsets, other pattern letters, optional sections, `getDisplayName` and printing a formatter are unsupported or engine limitations, as is a parse whose JDK message lists fields it could not resolve (the JDK's order of them changes from run to run). |
150
+ | **`java.time`** (ADRs 0025, 0029, 0032) | Supported with limits | `LocalDate` (`of`, `parse`, `ofEpochDay`, `ofYearDay`, `now()` from the browser's clock, the getters, `plus`/`minus` days, weeks, months and years (the day clamped to the month: `2024-01-31` plus a month is `2024-02-29`), `plus(long, TemporalUnit)`, `plus(TemporalAmount)`, `with…`, `atTime`, `atStartOfDay`, `isBefore`/`isAfter`/`isEqual`, `until`, `datesUntil`, `format`, `toString` with the JDK's year signs, `hashCode`, Comparable). `LocalTime` (`of`, `ofSecondOfDay`, `ofNanoOfDay`, `parse`, `now()`, `MIN`/`MAX`/`MIDNIGHT`/`NOON`, the getters, `plus`/`minus` hours to nanoseconds around the clock, `with…`, `truncatedTo`, `until`, `atDate`, `toSecondOfDay`, `toNanoOfDay`, `format`, `toString` as the JDK's: `09:05`, `01:02:03.400`, `01:02:03.000000007`). `LocalDateTime` (`of` with all its overloads, `parse`, `now()`, the date's and the time's getters and `with…`, `plus`/`minus` from years to nanoseconds with the days carried, `until` that leaves out an incomplete last day, `truncatedTo`, `toLocalDate`/`toLocalTime`, `format`, `2024-01-31T22:30`). `Duration` (`of…`, `between` two times or date-times, `parse`, `plus`/`minus`, `multipliedBy`, `dividedBy`, `negated`, `abs`, `truncatedTo`, `to…` and `to…Part`, `PT2H15M` and `PT-1M-29.5S`, long overflow as the JDK's `ArithmeticException`). `Period` (`between` with the JDK's borrow, `of…`, the getters, `normalized`, `multipliedBy`, `P1Y2M3D`), `DayOfWeek` and `Month` (`of`, `getValue`, `plus`, `minus`, `length`), `ChronoUnit` (`between` for any of the three types; a unit a type does not have is the JDK's `UnsupportedTemporalTypeException: Unsupported unit: Hours`), and `DateTimeFormatter` (`ofPattern` with the letters `y u M L d D E H h k K m s S n a`, quoted text and optional sections (`yyyy-MM-dd[ HH:mm[:ss]]`: printed when the value has their fields, tried and skipped when parsing), `ISO_LOCAL_DATE`, `ISO_LOCAL_TIME`, `ISO_LOCAL_DATE_TIME`). The parameter types are the JDK's interfaces (`Temporal`, `TemporalAmount`, `TemporalUnit`, `TemporalAccessor`), which a program can name. Mixing types works as on the JDK: `Duration.between(time, dateTime)` takes the date-time's time, the other way round is `Unable to obtain LocalDateTime from TemporalAccessor`, and `date.plus(duration)` is `Unsupported unit: Seconds`. Parsing resolves as the JDK's: an `ofPattern` formatter clamps `31/04` to April 30, the ISO ones reject `2024-02-30`, `h` needs `a`; the JDK's `DateTimeException` and `DateTimeParseException` messages, with the cause, and helpful `NullPointerException` messages. A switch on `DayOfWeek`, `Month`, `ChronoUnit` or `RoundingMode` takes their constants as labels. `now()` reads the clock to the millisecond (the JDK's to the microsecond). `Instant` (`ofEpochSecond`, `ofEpochMilli`, `parse`, `now()`, `EPOCH`/`MIN`/`MAX`, `plus`/`minus` up to days, `until`, `truncatedTo`, `atZone`, `toEpochMilli`, `2023-11-14T22:13:20.123Z`). `ZoneId` (`of` with region IDs, offsets and `UTC`/`GMT`/`UT` prefixes, `systemDefault()`, `normalized`, the JDK's `ZoneRulesException: Unknown time-zone ID` and invalid-format messages), `ZoneOffset` (`of` read as the JDK reads it, `ofHours`, `ofHoursMinutes`, `ofHoursMinutesSeconds`, `ofTotalSeconds`, `UTC`/`MIN`/`MAX`, the JDK's range and sign messages) and `ZonedDateTime` (`of`, `ofInstant`, `parse`, `now`, the getters, `withZoneSameInstant`/`withZoneSameLocal`, `withEarlierOffsetAtOverlap`/`withLaterOffsetAtOverlap`, `withFixedOffsetZone`, `plus`/`minus` with dates local and times on the instant, `until`, `truncatedTo`, `toInstant`, `toEpochSecond`, `2024-03-10T03:30-04:00[America/New_York]`). A zone's rules are the browser's (`Intl`): a daylight saving gap moves the time forward and an overlap keeps the earlier offset, as on the JDK; the browser's time zone data can be a different version from the JDK's. `LocalDateTime.atZone`, `toInstant(ZoneOffset)`, `toEpochSecond(ZoneOffset)`, `ofInstant`, `ofEpochSecond`, `LocalDate.atStartOfDay(ZoneId)`, `now(ZoneId)` and `from` on each type. The formatter's zone letters `VV`, `X`, `x` and `Z`, and `ISO_OFFSET_DATE_TIME`, `ISO_ZONED_DATE_TIME` and `ISO_INSTANT`. `ZoneRules` (`getRules()`), `OffsetDateTime` and `OffsetTime` (they exist only so that `date.atTime(null)` is ambiguous, as in javac), `Clock`, the localized letters `O`, `z`, `v` and `ZZZZ`, other pattern letters, `getDisplayName` and printing a formatter are unsupported or engine limitations, as is a parse whose JDK message lists fields it could not resolve (the JDK's order of them changes from run to run). |
150
151
  | `EnumMap`, `EnumSet` | Supported | An enum's constants in ordinal order. `EnumMap(Class)`, `(EnumMap)`, `(Map)` (an empty non-EnumMap is `IllegalArgumentException: Specified map is empty`), with every `Map` method; a null key is the JDK's NPE on `put` and simply absent on `get`, `containsKey` and `remove`. `EnumSet.noneOf`, `allOf`, `of` (one to five constants, or varargs), `range` (`C > A` when reversed), `complementOf`, `copyOf` (`Collection is empty`), `clone`, with every `Set` method plus `removeAll` and `retainAll`; its iterator walks a snapshot, so removing while iterating never fails, as on the JDK. `getClass()` is `java.util.EnumMap` and `java.util.RegularEnumSet` (`JumboEnumSet` above 64 constants). |
151
152
  | `java.math.BigInteger` | Supported | `ZERO`, `ONE`, `TWO`, `TEN`, `valueOf` (sharing -16..16 as the JDK does, so `valueOf(1) == ONE`), `new BigInteger(String[, radix])` with the JDK's messages (`Zero length BigInteger`, `For input string: "x10"` naming the failing digit group, `Radix out of range`, `Illegal embedded sign character`); `add`, `subtract`, `multiply`, `divide`, `remainder`, `mod`, `divideAndRemainder`, `pow`, `modPow`, `modInverse`, `gcd`, `abs`, `negate`, `signum`, `sqrt`, `min`, `max`, `compareTo`, `equals`, `hashCode` (the JDK's), `toString` (any radix), the `…Value` and `…ValueExact` conversions, bit operations (`shiftLeft`, `and`, `testBit`, `bitLength`, `bitCount`, …), `isProbablePrime`, `nextProbablePrime`, with the JDK's `ArithmeticException` messages. `%d`, `%x` and `%o` format it (signed: `-ff`). Comparable, so it sorts and keys TreeMaps; content-equal in HashMaps. Non-ASCII digits are an engine limitation; `probablePrime` and `toByteArray` are unsupported. |
152
153
  | `java.math.BigDecimal`, `RoundingMode`, `MathContext` | Supported | A BigInteger unscaled value and a scale, as the JDK's: `new BigDecimal(String)` (with its messages), `(double)` (the double's exact value: `0.1000000000000000055511151231257827021181583404541015625`), `(int)`, `(long)`, `(BigInteger[, scale])`, `valueOf(double)` (via `Double.toString`), `valueOf(long[, scale])` (sharing 0..10 as the JDK does); `add`, `subtract`, `multiply` (scale rules as documented), `divide` exact (the preferred scale, or the smallest that holds the quotient: `5 / 0.25` is `2E+1`; `Non-terminating decimal expansion; no exact representable decimal result.`), with a scale and `RoundingMode`, or a `MathContext`; `divideToIntegralValue`, `remainder`, `setScale` (`Rounding necessary`), `round`, `sqrt`, `pow`, `movePointLeft`/`Right`, `scaleByPowerOfTen`, `stripTrailingZeros`, `precision`, `unscaledValue`, `compareTo` (by value) and `equals` (value and scale: `1.10` is not `1.1`), `hashCode` (the JDK's), `toString` (scientific when the JDK's is: `1E+2`, `1.234E-7`), `toPlainString`, the conversions. All eight `RoundingMode`s (`values()`, `valueOf`, `name`, `ordinal`) and `MathContext` (`DECIMAL32`, `DECIMAL64`, `DECIMAL128`, `UNLIMITED`, its constructors). `%f`, `%e` and `%g` format a BigDecimal from its exact digits. Scanner's `nextBigInteger` and `nextBigDecimal` read them. The `MathContext` forms of `add` and the other arithmetic, `ulp` and `toEngineeringString` are unsupported. |
@@ -184,7 +185,7 @@ These all use javac's wording and caret positions, as evidenced by `tests/jdk-ca
184
185
  - `non-static … cannot be referenced from a static context`
185
186
  - `… has private access in …`
186
187
  - `invalid method declaration; return type required`, `modifier static not allowed here`, `explicit constructor invocation may only appear within a constructor body`
187
- - **Method and constructor calls:**
188
+ - **Method and constructor calls** (0.37.0 brought javac's longer forms, ADR 0031: a generic owner with its type variables, `method put in interface Map<K,V>`, and its `where` lines; a generic library candidate as declared, `Collections.<T#1>sort(List<T#1>)`, with javac's inference reasons and numbered type variables; a lambda argument whose body does not fit, reported as the call's argument mismatch; a diamond that cannot be inferred, `cannot infer type arguments for Pair<>`; a wildcard receiver captured, `List.add(CAP#1)`; every JDK overload a call could mean, listed in the JDK's order):
188
189
  - `method f in class Main cannot be applied to given types;` with `required`/`found`/`reason` (and the same for constructors)
189
190
  - `no suitable method found for …` / `no suitable constructor found for …`, with every candidate and why it does not apply
190
191
  - `reference to f is ambiguous`
@@ -192,7 +193,7 @@ These all use javac's wording and caret positions, as evidenced by `tests/jdk-ca
192
193
  - **Reachability (JLS 14.22):** after `return`/`break`/`continue`, after loops that cannot exit, and for a `while (false)` or `for (; false; )` body. `if (false)` is allowed.
193
194
  - **`missing return statement`**
194
195
  - **Error order:** one top-level class at a time, in source order: its attribution errors (nested classes where they are declared), then reachability, then definite assignment, with nested classes first. **Once any error has been reported, flow analysis does not run**, exactly as in javac, so a type error hides a missing return in the same file, and so does an error in an earlier class.
195
- - **Syntax, lexical, and number-literal errors:** as in 0.1.0.
196
+ - **Syntax, lexical, and number-literal errors:** as in 0.1.0, and since 0.35.0 every one of them, as javac's recovery finds them (ADR 0030): a missing `;`, `)`, `]`, `}` or `>` is reported and taken as there; an expression or statement that cannot be read is reported and skipped to the next statement; a cascade from one mistake is not reported; a lexical error (`"hi;`, `'ab'`, `#`) is reported where the parse reaches it, and silences what follows from it. With a syntax error in the file, as with javac, no other kind of error is reported. At most 100 errors are shown, with javac's `only showing the first 100 errors` line.
196
197
 
197
198
  **Output format:** the same as `java Main.java`. **Warnings:** none (JDK 25 source-file mode prints none for these programs either).
198
199
 
@@ -228,10 +229,9 @@ These all use javac's wording and caret positions, as evidenced by `tests/jdk-ca
228
229
  | Case | JDK 25 | Engine | How the tests compare it |
229
230
  | --- | --- | --- | --- |
230
231
  | Exceptions thrown inside the JDK (`charAt` out of range, `println` of a null `char[]`, any library method), inside a `toString()` called by `println`, `+` or a collection, or during class initialization or instance creation; and every trace `printStackTrace()` prints | The program's frames plus the JDK's own frames (`at java.base/…` such as `String.valueOf`, the source launcher's five frames below `main`, `at jdk.compiler/…`) | Same messages and program frames, without the JDK's frames. `... N more` counts the launcher's frames, so it is the JDK's number | Identical once the JDK's frames are removed |
231
- | `no suitable method found for sort(...)` with a generic `Arrays.sort` candidate | javac prints the generic overloads as `Arrays.<T#1>sort(…)` with inference details and a `where` clause | The overloads the engine has, with substituted types | Each error's header, source line and caret identical |
232
+ | `no suitable method found for sort(...)` with a generic `Arrays.sort` candidate given an array of arrays or a lambda it cannot type | Inference details such as `upper bounds: int[],Object` | The candidates as javac lists them (`Arrays.<T#1>sort(T#1[],…)`, its `where` clause), with a narrower reason for those | Each error's header, source line and caret identical |
232
233
  | `StackOverflowError` trace length | Capped at 1024 frames; 1019 were printed in the recorded case | 1024 frames | First lines identical |
233
- | A lexical error (`int #x`, unclosed comment, unclosed text block) | Follow-on syntax errors after javac's error recovery | The lexical error only | First diagnostic identical |
234
- | Several syntax errors in one file | javac may report several | The engine stops at the first | (by design, ADR 0001) |
234
+ | Several syntax errors in one file, lexical ones among them | Every one javac's recovery finds | The same errors in nearly every case: the engine recovers as javac does (ADR 0030; 87 recorded cases of beginners' mistakes). Where its recovery takes another path, the first error is still javac's, and later ones may differ (`void static() { }`; an unclosed text block whose `\"""` hides its end) | Identical for the recorded cases; first diagnostic for the one text block case |
235
235
  | Printing an array or an object without `toString()` (`[I@5fdba6f9`, `Node@6dde5c8c`), or `hashCode()` | Random identity hash | Deterministic per-run hash with the same format | Format checked by unit tests |
236
236
  | `Math.sin`, `exp`, `pow`, `log` and the other transcendental functions | Results of the platform's math library | JavaScript's; about 3% of probed values differed in the last digit (accepted by the owner, 2026-10-18) | The recorded cases print them with `printf("%.12f")`; unit tests allow a few ulps. Java permits this: `Math`, unlike `StrictMath`, need not be reproducible across platforms |
237
237
  | Unseeded `new Random()`, `Math.random()`, `System.currentTimeMillis()`, `nanoTime()`, `identityHashCode` | Differ on every run | Differ on every run (identity hashes are per-run, as above) | Ranges checked by unit tests |
package/README.md CHANGED
@@ -9,7 +9,7 @@ entirely in the reader's browser. No backend, no iframe, no sign-up.
9
9
  **[Live demo →](https://code-playpad.swengr.com)**
10
10
 
11
11
  ```html
12
- <script type="module" src="https://cdn.jsdelivr.net/npm/code-playpad@0.7.0/dist/standalone.js"></script>
12
+ <script type="module" src="https://cdn.jsdelivr.net/npm/code-playpad@0.9.0/dist/standalone.js"></script>
13
13
 
14
14
  <code-playpad height="auto">
15
15
  print("hello from a static page")
@@ -159,6 +159,20 @@ under a second. The engine stops a runaway program after 200 million steps
159
159
  the evidence behind it and every known difference from the JDK, is in
160
160
  [JAVA-COMPATIBILITY.md](https://cdn.jsdelivr.net/npm/code-playpad/JAVA-COMPATIBILITY.md), which ships in the package.
161
161
 
162
+ ## Experimental C/C++
163
+
164
+ `language="c"` (C17) and `language="cpp"` (C++20) compile and run in a worker
165
+ with a real Clang compiler, prefilled stdin and Stop. They are experimental:
166
+
167
+ - **You host the compiler.** It is not in the npm package and there is no
168
+ hosted copy yet. Build the pinned toolchain from this repository, host it,
169
+ and call `configureCpp({ indexURL })`. Without that, Run explains what is
170
+ missing and downloads nothing.
171
+ - **Not yet tested on physical phones.** Desktop Chromium, WebKit and Firefox
172
+ pass; iPhone Safari and Android Chrome have not been run.
173
+
174
+ See [setup and limits](https://github.com/stancs/code-playpad/blob/main/docs/COMPILER-RUNTIMES.md).
175
+
162
176
  ## Download size
163
177
 
164
178
  What a page downloads once a reader presses Run, with the CDN build, as
@@ -171,33 +185,46 @@ actually sent.
171
185
  | Python | **166.3 KB** | Pyodide, about **6.0 MB** (a 3.3 MB wasm file and a 2.4 MB standard library) | 165.8 KB |
172
186
  | JavaScript | **180.4 KB** | nothing | 179.9 KB |
173
187
  | TypeScript | **227.3 KB** (0.5.2: with the 46.9 KB transform) | nothing (before 0.5.2: Sucrase from esm.sh, 72 KB) | 179.9 KB |
174
- | Java | **279.8 KB** (0.7.0: engine 0.34) | nothing | 216.4 KB |
175
- | Java, with collections | **363.4 KB** (0.7.0) | nothing | 233.2 KB |
176
- | All four | 467.8 KB (0.7.0) | Pyodide | 273.9 KB |
188
+ | Java | **288.1 KB** (0.8.0: engine 0.39) | nothing | 216.4 KB |
189
+ | Java, with collections | **373.1 KB** (0.8.0) | nothing | 233.2 KB |
190
+ | C or C++ (experimental) | **187.0 KB** | the compiler, about **29.9 MB**, from the host you configure | — |
191
+ | All five | 520.0 KB | Pyodide and the C/C++ compiler | 273.9 KB |
177
192
 
178
193
  - **Every row includes a 144.5 KB shared base:** the editor (CodeMirror) and
179
194
  the widget, the same as in 0.3.0.
180
195
  - **Each language adds:**
181
196
  - Python: 21.7 KB.
182
197
  - JavaScript/TypeScript: 35.9 KB.
183
- - Java: 135.2 KB (the 116.2 KB engine plus 19 KB of Java syntax
198
+ - Java: 143.5 KB (the 124.5 KB engine plus 19 KB of Java syntax
184
199
  highlighting).
185
200
  - The first Java program that uses collections, `StringBuilder` or another
186
- library class also adds the 83.6 KB Java library, once per page.
201
+ library class also adds the 85.0 KB Java library, once per page.
187
202
  - Since 0.7.0, four parts of the library load only for the first program
188
- that uses them: `java.time` 11.5 KB, `java.math` 6.7 KB,
203
+ that uses them: `java.time` 16.8 KB, `java.math` 6.7 KB,
189
204
  `Pattern`/`Matcher` 2.7 KB and `BitSet` 2.3 KB. The rows above leave
190
205
  them out.
191
- - The Java figures for 0.7.0 are the 0.4.0 measurements plus what the
206
+ - C/C++: 42.5 KB (the 7.9 KB runtime plus 34.6 KB of C/C++ syntax
207
+ highlighting). See the C/C++ note below.
208
+ - The Java figures for 0.8.0 are the 0.4.0 measurements plus what the
192
209
  engine's two chunks changed by in the build's gzip sizes (engines 0.28
193
- to 0.34 added the collection staples, library subclasses, the tutorial
194
- APIs, regex, java.time and more; 0.32 moved the rarely used classes out
195
- of the library).
210
+ to 0.39 added the collection staples, library subclasses, the tutorial
211
+ APIs, regex, java.time, javac's error recovery and messages, packages
212
+ and more; 0.32 moved the rarely used classes out of the library).
213
+ - **C and C++ (experimental)** were measured on 2026-10-29 as
214
+ the difference between pages with and without C/C++. Measured that day,
215
+ whole pages come out 4–8 KB larger than this table, with or without the
216
+ C/C++ code, so the C/C++ and All five rows add the measured 42.5 KB to this
217
+ table's figures. The compiler is the large part: Clang 15.2 MB, the linker 8.8 MB,
218
+ and headers and libraries 5.9 MB, gzipped as a host would typically send
219
+ them. It downloads on the first Run, from the address given to
220
+ `configureCpp` (you host it), and is cached after that. C and C++ share it, so a page
221
+ with both downloads it once. 0.3.0 had no C/C++, so its All five figure is
222
+ its four-language page.
196
223
  - **Java grew** from 0.3.0 because the subset did, from basic Java to most of
197
224
  what practice programs use (see the version history). The owner treats
198
225
  download size as secondary to coverage. The package's size checks still
199
226
  catch accidental growth: 128 KiB for the Java chunk, 96 KiB for its
200
- library and 16 KiB for each part of it.
227
+ library and 24 KiB for each part of it.
201
228
  - **Languages load lazily.** A Java page never fetches the Python or
202
229
  JavaScript runtimes, and Python and JavaScript pages never fetch Java. As a
203
230
  result, Python-only and JavaScript-only pages are the same size as in 0.3.0.
@@ -217,7 +244,7 @@ actually sent.
217
244
  ### From a CDN — nothing to install
218
245
 
219
246
  ```html
220
- <script type="module" src="https://cdn.jsdelivr.net/npm/code-playpad@0.7.0/dist/standalone.js"></script>
247
+ <script type="module" src="https://cdn.jsdelivr.net/npm/code-playpad@0.9.0/dist/standalone.js"></script>
221
248
  ```
222
249
 
223
250
  This is the `standalone` build: CodeMirror is bundled in, so a static blog post
@@ -848,7 +875,64 @@ warms every other page on the site.
848
875
 
849
876
  ## Version history
850
877
 
851
- Markup and API written against 0.1.3 still work on 0.7.0, with one exception, in
878
+ ### 0.9.0
879
+
880
+ Adds experimental C and C++. Nothing else changed: Python, JavaScript,
881
+ TypeScript and Java behave as in 0.8.0, and existing pages grow by about
882
+ 0.5 KB.
883
+
884
+ - **`language="c"` and `language="cpp"`** (C17 and C++20) compile with Clang 20
885
+ and link with LLD, compiled to WebAssembly, in a worker. Multiple files,
886
+ prefilled stdin, Stop, a wall-clock limit and streamed output all work.
887
+ Programs get stdin, stdout and stderr only; exceptions and threads are not
888
+ supported, and live interactive stdin is not implemented.
889
+ - **`configureCpp({ indexURL })` is required.** The compiler (about 29.9 MB
890
+ gzipped) is not in this package and has no hosted copy yet, so you build and
891
+ host it yourself. Its files are checked by SHA-256 and cached after the first
892
+ Run. Without the setting, Run explains what is missing and downloads nothing.
893
+ - **Tested on desktop only:** Chromium, WebKit and Firefox. Physical iPhone and
894
+ Android runs have not been done.
895
+ - **`RunOptions`** gains `onProgress` and `timeoutMs`, and `Result` gains
896
+ `memory`.
897
+ - **New optional peer dependency:** `@codemirror/lang-cpp`, for highlighting
898
+ with a bundler.
899
+
900
+ ### 0.8.0
901
+
902
+ Java engine 0.34.1 → 0.39.0, each change checked against JDK 25. Nothing
903
+ else changed: Python, JavaScript and TypeScript, the element's API and its
904
+ markup are as in 0.7.0. One Java behavior a page may notice: a file in a
905
+ folder (`util/Tool.java`) used to be reported as unsupported; it is now a
906
+ class of that folder's package, as on the JDK.
907
+
908
+ - **Every syntax error, as javac reports them.** A program with two missing
909
+ semicolons now shows both errors, not just the first, with javac's
910
+ wording and carets; a mistake that confuses the parser does not produce a
911
+ cascade of errors javac would not show. Unclosed string and character
912
+ literals no longer hide the syntax errors after them.
913
+ - **Optional sections in date patterns.** `DateTimeFormatter.ofPattern`
914
+ takes `[...]` sections (`yyyy-MM-dd[ HH:mm[:ss]]`), as the JDK does, and
915
+ `date.atTime(null)` is javac's ambiguity error.
916
+ - **javac's longer error messages.** A call that does not fit names the
917
+ method's owner and its type variables as javac does (`method put in
918
+ interface Map<K,V>`), candidate lists show generic methods as declared
919
+ (`Collections.<T#1>sort(List<T#1>)`) and every JDK overload, and a lambda
920
+ whose body does not fit is reported as the call's mismatch. Calls javac
921
+ rejects but the engine ran, such as `add(1)` on a
922
+ `List<? extends Number>`, are now errors.
923
+ - **Instants and time zones.** `Instant`, `ZoneId`, `ZoneOffset` and
924
+ `ZonedDateTime`, with the browser's time zone rules and the JDK's handling
925
+ of daylight saving gaps and overlaps
926
+ (`2024-03-10T03:30-04:00[America/New_York]`), the formatter's zone letters
927
+ (`VV`, `X`, `x`, `Z`) and the ISO offset, zoned and instant formats.
928
+ - **Packages.** Java files in folders: `util/Tool.java` declares
929
+ `package util;`, and files in other folders import it, with javac's
930
+ import rules and its errors for access across packages. A helper file that
931
+ the launch file needs only for its declarations is compiled when its class
932
+ first loads, as the JDK's launcher does, so its errors appear at that
933
+ point in the run.
934
+
935
+ Markup and API written against 0.1.3 still work on 0.9.0, with one exception, in
852
936
  0.5.1: an `entry` that names none of a widget's files is now an error.
853
937
 
854
938
  ### 0.7.0
@@ -1148,6 +1232,12 @@ their own MIT licences, reproduced in full in `dist/THIRD-PARTY-NOTICES.txt`.
1148
1232
  Pyodide (MPL-2.0) is fetched from a CDN at runtime and is not redistributed by
1149
1233
  this package.
1150
1234
 
1235
+ Experimental C/C++ downloads separate compiler assets with additional
1236
+ third-party terms; those assets are not MIT-only. Their notices ship in
1237
+ `dist/COMPILER-NOTICES.txt`. The pinned C/C++ rebuild passes its scoped license
1238
+ inventory gate; see the [compiler license audit](docs/COMPILER-LICENSE-AUDIT.md)
1239
+ and [rebuild and remaining gates](docs/CPP-REBUILD.md).
1240
+
1151
1241
  The Java engine is original code under the same MIT licence. Java is a trademark
1152
1242
  of Oracle and/or its affiliates; code-playpad is not affiliated with, endorsed
1153
1243
  by, or certified by Oracle, and its Java support is a documented subset, not a
@@ -0,0 +1,104 @@
1
+ # Compiler license audit — 2026-10-27
2
+
3
+ **Disposition: the project's own code remains MIT. The license inventory gate
4
+ passes for the pinned rebuilt C/C++ artifact set and its notice companions.**
5
+ Release still needs the owner's approval. The old browsercc
6
+ binary set is superseded, not retroactively cleared. See [CPP-REBUILD.md](CPP-REBUILD.md)
7
+ for exact scope, build evidence and remaining non-license release gates.
8
+
9
+
10
+ ## What is cleared and what was added
11
+
12
+ The bundled integration uses `@bjorn3/browser_wasi_shim` 0.4.2 under its MIT option
13
+ and adapts the MIT Weblings worker protocol/sysroot format at
14
+ `d0cd7a9f3af7d8249b3948ac0e19d2afc0d01633`. Their full notices already reside in
15
+ `dist/THIRD-PARTY-NOTICES.txt`; the distribution check now verifies both the names
16
+ and complete text. The CodeMirror C++ grammar retains its MIT notice too.
17
+ The project's LICENSE is unchanged. No compiler binaries are committed or packed.
18
+
19
+ Added a separate `third-party/compiler/manifest.json` and source notice corpus.
20
+ Each snapshot records its immutable source URL and SHA-256. The build emits
21
+ `dist/COMPILER-NOTICES.txt`, this audit, and `compiler-license-manifest.json` so
22
+ npm consumers receive the findings and available external notices. The local
23
+ asset-preparation script also copies these companions beside each toolchain.
24
+ The rebuilt C/C++ additions resolve its scoped inventory gaps.
25
+
26
+ `npm run check:compiler-licenses` verifies notice hashes. Adding `-- --release`
27
+ fails until the owner sets `releaseApproved`. Use `-- --release --toolchain=cpp`
28
+ for the rebuilt C/C++ license gate, which passes. This is an explicit
29
+ compiler release gate, not a claim that a normal build is approved for release.
30
+
31
+ ## Historical browsercc C/C++ findings (superseded by the pinned rebuild)
32
+
33
+ The reviewed npm archive is browsercc 0.1.1, source
34
+ `86168bacf0fe7c662e3e65a2e3006ceb159cd0dc`; exact asset hashes are recorded in
35
+ `src/runtime/cpp/assets.ts` and the audit manifest. The wrapper's MIT LICENSE
36
+ has no explicit copyright-holder line; it is preserved verbatim. Package metadata
37
+ names Daniel Bertalan as author; no invented copyright line was added.
38
+
39
+ The recipe builds Clang/LLD from LLVM 20.1.2 (`58df0ef89dd64126512e4ee27b4ac3fd8ddf6247`).
40
+ It obtains libc++, libc++abi and compiler builtins from WASI SDK 25's LLVM revision
41
+ `ab4b5a2db582958af1ee308a790cfdb42bd24720`, and wasi-libc revision
42
+ `574b88da481569b65a237cb80daf9a2d5aeaf82d`. These are distinct LLVM inputs.
43
+ Their primary license texts are retained, including LLVM exceptions and legacy
44
+ NCSA terms. wasi-libc's umbrella references Apache/LLVM, Apache, MIT, cloudlibc
45
+ BSD-2-Clause, musl MIT, musl-fts BSD-3-Clause and allocator notices; these referenced
46
+ texts and allocator attribution headers are included.
47
+
48
+ The recipe explicitly removes sysroot `share/` and VERSION (share/ was later
49
+ confirmed to contain symbol/configuration data, not a standalone license bundle),
50
+ and the distributed
51
+ sysroot contains no standalone license/copyright files. It also selects Emscripten
52
+ `latest`, with no immutable SDK revision or complete linked-host-library list.
53
+ The compiler Wasm files contain no producer/custom metadata that resolves that
54
+ version. Root LLVM notices explicitly defer to component/file-level third-party
55
+ terms; copying only the root license is not a complete compiler notice bundle.
56
+
57
+ **Historical C/C++ blockers (resolved by replacement):** obtain upstream provenance plus a complete notice/SBOM bundle,
58
+ or rebuild from pinned LLVM, Emscripten and WASI inputs while preserving notices.
59
+ Account for Emscripten glue, linked libc/libc++/allocator code, and LLVM's included
60
+ third-party code. Compare any replacement hashes and rerun browser/size tests.
61
+ The current CDN pointer does not make the missing attribution irrelevant.
62
+
63
+ ## Rust (removed 2026-10-29)
64
+
65
+ An experimental Rust runtime was removed before release. Its compiler came
66
+ from a fork whose custom backend commits carry no license of their own, so no
67
+ license review could clear it. The owner chose not to seek one; any future Rust
68
+ runtime would replace those commits with project-authored code. Its audit, notice
69
+ corpus and evidence remain in git history on branch `codex/c-cpp-runtime`.
70
+
71
+ ## Distribution and generated user programs
72
+
73
+ Retain upstream copyright/license texts and applicable NOTICE files; identify
74
+ modified upstream files where required by their licenses. Our separately authored
75
+ integration remains MIT. Upstream recipe modifications (sysroot rearrangement,
76
+ added bits/stdc++.h and stripped sections) are not our original authorship and need provenance in any replacement distribution.
77
+
78
+ Compiling a user's program does not by itself relicense its original source.
79
+ Linked libc/libc++ and other runtime code have their own terms. LLVM's
80
+ exception is relevant to embedded object code, not a blanket exemption for
81
+ redistributing the compiler, unrelated libraries or all generated programs.
82
+ Don't tell downstream users that every output is automatically MIT or obligation-free.
83
+
84
+ ## Release checklist / owner actions
85
+
86
+ 1. Keep C/C++ scoped to the rebuilt, verified hashes and notice companions.
87
+ 2. Publish complete, immutable compiler distributions with companion notices;
88
+ test the actual CDN compression, CORS and notice URLs. Current transfers are
89
+ measured with a local gzip mirror, not verified production hosting.
90
+ 3. Complete physical iPhone Safari and Android Chrome memory/lifecycle/cache
91
+ testing. Desktop Chromium, WebKit and Firefox pass 22 checks each.
92
+ 4. Run the packed React/bundler/CSP checks, and decide interactive-input scope.
93
+ See compiler-validation.md for the detailed non-license gates.
94
+
95
+ Sources: immutable URLs for every retained text are in the manifest; the build
96
+ recipe is [browsercc](https://github.com/BertalanD/browsercc/blob/86168bacf0fe7c662e3e65a2e3006ceb159cd0dc/build.sh),
97
+ superseded by the pinned rebuild in `toolchains/cpp/`.
98
+
99
+ Validation: notice hashes, 77 tests, typecheck, build and distribution checks pass.
100
+ The npm dry-run (2026-10-29, after Rust's removal) contains all three audit
101
+ companions (932,733 bytes compressed, 77 files). Local asset preparation copies
102
+ them beside the toolchain. The combined release check fails until the owner
103
+ approves release; the rebuilt C/C++ check passes; successful packaging is not
104
+ release clearance.