code-playpad 0.5.1 → 0.6.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.
- package/JAVA-COMPATIBILITY.md +39 -33
- package/README.md +91 -14
- package/dist/THIRD-PARTY-NOTICES.txt +347 -0
- package/dist/cdn.js +2 -2
- package/dist/config-D9w0xYhX.js +6 -0
- package/dist/{element-CthH7rm5.js → element-9sv2r5Jv.js} +1 -1
- package/dist/element.js +1 -1
- package/dist/index.js +1 -1
- package/dist/java-C08pjr71.js +6 -0
- package/dist/java-library.generated-9nfQ3go0.js +6 -0
- package/dist/java-xCWvYPkx.js +1 -0
- package/dist/javascript-BIBG4Etb.js +9 -0
- package/dist/javascript-CX-lsX2u.js +14 -0
- package/dist/{pyodide-FRnMyCht.js → pyodide-5mtewJ6F.js} +1 -1
- package/dist/{pyodide-BeJ9RqWJ.js → pyodide-Crdd9em4.js} +1 -1
- package/dist/react.js +1 -1
- package/dist/runtime/config.d.ts +6 -3
- package/dist/runtime/java-library.generated.d.ts +3 -3
- package/dist/runtime/java-worker.generated.d.ts +3 -3
- package/dist/runtime/javascript.d.ts +3 -0
- package/dist/runtime/js-worker.d.ts +5 -3
- package/dist/runtime/sucrase-chunk.generated.d.ts +2 -0
- package/dist/runtime/sucrase.generated.d.ts +5 -0
- package/dist/standalone.js +1 -1
- package/dist/sucrase-3.35.1.js +6 -0
- package/dist/{worker-runtime-owJ7Wwco.js → worker-runtime-DXqFOKYs.js} +1 -1
- package/package.json +3 -1
- package/dist/config-DZqcFPEP.js +0 -6
- package/dist/java-C6Gdqz5p.js +0 -6
- package/dist/java-Dd7T9rVc.js +0 -1
- package/dist/java-library.generated-I0MB-4YJ.js +0 -6
- package/dist/javascript-BiwxX4vc.js +0 -9
- package/dist/javascript-EtrNZmfD.js +0 -14
package/JAVA-COMPATIBILITY.md
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
<!-- GENERATED by scripts/sync-java.mjs from java-online-compiler@0.
|
|
1
|
+
<!-- GENERATED by scripts/sync-java.mjs from java-online-compiler@0.31.0 (1e282082ba6882cd5be2b0f512ee0c64544799b4). Do not edit. -->
|
|
2
2
|
|
|
3
|
-
> This is the compatibility table of the Java engine that code-playpad ships (engine 0.
|
|
3
|
+
> This is the compatibility table of the Java engine that code-playpad ships (engine 0.31.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.
|
|
6
|
+
# Compatibility — engine 0.31.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)
|
|
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
|
|
|
@@ -15,9 +15,9 @@ Every feature has one status:
|
|
|
15
15
|
|
|
16
16
|
> **Evidence:** everything below is checked against the pinned JDK, Temurin 25.0.4.1 (docs/reference-jdk.md).
|
|
17
17
|
> - **Golden programs:** all 47 in `tests/programs` (the SPEC.md §4.1 Stage A corpus among them) match byte for byte: stdout, stderr, and exit code.
|
|
18
|
-
> - **Recorded snippets:** all
|
|
18
|
+
> - **Recorded snippets:** all 1636 cases in `tests/jdk-cases` match. 1613 match byte for byte (once the JDK's own stack frames are removed, as *Known divergences* explains); the other 23 are listed under *Known divergences*, each with the narrower comparison the tests apply to it.
|
|
19
19
|
> - **Practice corpus:** all 10 Stage 4 programs in `tests/corpus` (docs/practice-corpus.md) run and match.
|
|
20
|
-
> - **Field corpus:**
|
|
20
|
+
> - **Field corpus:** 336 of 339 programs written as learners and solvers write Java, kept whether or not the engine supports them, match the JDK exactly. None runs differently; 1 is rejected as unsupported (`Thread`), 2 stop on an engine limitation and none on the instruction limit (`corpus/REPORT.md`, docs/corpus-harness.md).
|
|
21
21
|
|
|
22
22
|
## Program structure
|
|
23
23
|
|
|
@@ -25,7 +25,7 @@ Every feature has one status:
|
|
|
25
25
|
| --- | --- | --- |
|
|
26
26
|
| **Compact source files** (Java 25): top-level methods, fields and classes, with no class declaration | Supported | They form an implicitly declared class named after the file (`Main` for `Main.java`), which the program cannot refer to by name (`Main.f()` is `cannot find symbol`, as in javac). Classes declared in the file are its member classes: inner unless `static`, named `Main$Node` at run time and `Main.Node` in diagnostics, as javac does. |
|
|
27
27
|
| **Several top-level classes** | Supported | Any number, in any order, each with its own fields, methods and constructors. `duplicate class: Node`. A public class need not match the file name (source-file mode allows it). |
|
|
28
|
-
| **Member classes**: `static` nested and inner | Supported with limits | `static class Node` inside `Main`, or an inner class, whose instances hold their enclosing instance (`this$0`) and can use its fields and methods by simple name. `new Inner()` needs an enclosing instance (`non-static variable this cannot be referenced from a static context`). Names: `Main$Node` at run time, `Node` in diagnostics, `Main.Node` as a qualified type. Classes nest to any depth (`static class MyList<T> { class Node { T val; } }`): an inner class reaches each enclosing instance through javac's `this$N` fields, so NPE messages name them as the JDK does. An inner class of a generic class, seen from outside it, keeps its outer class's type variables. `Outer.this` names an enclosing instance. `outer.new Inner()` is unsupported. |
|
|
28
|
+
| **Member classes**: `static` nested and inner | Supported with limits | `static class Node` inside `Main`, or an inner class, whose instances hold their enclosing instance (`this$0`) and can use its fields and methods by simple name. `new Inner()` needs an enclosing instance (`non-static variable this cannot be referenced from a static context`). Names: `Main$Node` at run time, `Node` in diagnostics, `Main.Node` as a qualified type. Classes nest to any depth (`static class MyList<T> { class Node { T val; } }`): an inner class reaches each enclosing instance through javac's `this$N` fields, so NPE messages name them as the JDK does. An inner class of a generic class, seen from outside it, keeps its outer class's type variables. `Outer.this` names an enclosing instance. `outer.new Inner()` (JLS 15.9.2) gives the enclosing instance explicitly, with javac's `NullPointerException` for a null one and `qualified new of static class`; with an anonymous class body, or of a generic class or a generic class's inner class, it is unsupported. |
|
|
29
29
|
| **Launch protocol** (Java 25) | Supported | The first top-level class runs if it has a `main`, otherwise the class named after the file (`can't find class: Main` if there is none). `main(String[])` is preferred over `main()`. Either may be `static` or an instance method, and need not be `public` (but not `private`). An instance `main` runs on an instance made with the no-argument constructor, which may be private (`can't find no argument constructor in class: A`). `String... args` and `String args[]` are accepted; `args` is empty. |
|
|
30
30
|
| Methods: parameters, `return`, recursion, overloading; `static` and instance | Supported | Overload resolution follows JLS 15.12.2: the strict phase, then the boxing phase, then the most specific method, with javac's "cannot be applied", "no suitable method", and "ambiguous" reports. Calls are `f(x)`, `this.f(x)`, `obj.f(x)`, `Node.f(x)`, or an enclosing class's `f(x)`. Using an instance member from a static context gives javac's `non-static … cannot be referenced from a static context`. |
|
|
31
31
|
| **Constructors** | Supported with limits | Overloaded, with javac's resolution errors (`constructor Point in class Point cannot be applied to given types;`, `no suitable constructor found for Point(String)`, `reference to Pair is ambiguous`). A class without one gets the default constructor. `this(...)` as the first statement, with `recursive constructor invocation` detected. Statements before `this(...)` (Java 25's flexible constructor bodies) and `super(...)` are unsupported. |
|
|
@@ -34,16 +34,16 @@ Every feature has one status:
|
|
|
34
34
|
| **Class initialization** (JLS 12.4) | Supported | Each class initializes on its first active use (`new`, a static method call, a non-constant static field), not at startup; reading a constant does not initialize it. An exception in a static initializer becomes `ExceptionInInitializerError` where the class was first used, with `Caused by:`. |
|
|
35
35
|
| Access | Supported | `private` members are visible within their top-level class, nested classes included: `secret has private access in Box`, `hide() has private access in Box`, `Box() has private access in Box`. `public`, `protected` and package access are equivalent here (one package). |
|
|
36
36
|
| `toString()`, `equals(Object)`, `hashCode()` | Supported | Declared or inherited, they are used wherever the JDK uses them: string conversion and `println`, `HashMap` and `HashSet` keys, `List.contains`. Without them, `Object`'s: `Node@hash` and identity. `super.toString()` is `Object`'s own. `@Override` is checked with javac's reasons. |
|
|
37
|
-
| **Inheritance** (`extends`, JLS 8.1.4) | Supported with limits | A class extends one class of the program: inherited fields and methods, overriding with dispatch on the object's class, `super(...)` (or the implicit `super()`), `super.f()` and `super.x`, covariant return types, field hiding, static methods inherited and hidden. Superclass constructors and field initializers run first, so a superclass constructor calling an overridden method sees the subclass's fields at their defaults, as on the JDK. `abstract` classes and methods, `final` classes and methods, `protected`. javac's errors: `B is not abstract and does not override abstract method f() in A`, `A is abstract; cannot be instantiated`, `cannot inherit from final A`, `f() in B cannot override f() in A` (with `overridden method is final`, `attempting to assign weaker access privileges; was public`, `return type long is not compatible with int`, `overriding method is static`), `cyclic inheritance involving A`, `abstract method f() in A cannot be accessed directly`, `x has private access in A` for a superclass's private member. NPE messages name the receiver's static type (`Cannot invoke "Main$B.f()"`), as the JDK does. A class may also extend the JDK's exception classes (*Exceptions* below). Extending other library classes, extending an inner (non-static) class, and statements before `super(...)` (Java 25's flexible constructor bodies) are unsupported. |
|
|
38
|
-
| **Interfaces** (JLS 9) | Supported with limits | Interfaces of the program, nested or top-level: abstract methods, `default` methods, `static` methods, `private` methods, constants; `extends` among interfaces; a class implementing several. Implementing methods must be `public` (`g() in C cannot implement g() in I`), and two unrelated defaults conflict (`types I and J are incompatible;`). A class may also implement the library's `Comparable<T>`, `Comparator<T>`, `Iterable<T>` and `Iterator<T>`: then sorting, `PriorityQueue`, `Collections.sort`, for-each and `Objects.compare` call its methods as Java code. `Interface.super.f()` calls a direct superinterface's default method (JLS 15.12.3), also from an interface extending it and inside a lambda, with javac's errors: `not an enclosing class: I` (not a direct superinterface, or a static context), `bad type qualifier I in default super call` (`redundant interface I is extended by J`), `abstract method m() in I cannot be accessed directly`, `illegal static interface method call`. `Main.super.f()` in Main is `super.f()`; `Outer.super.f()` for an enclosing class and implementing other library interfaces are unsupported. |
|
|
39
|
-
| The `Object` type | Supported | Variables, parameters, fields, arrays (`Object[]`), returns. Any value converts to `Object` (primitives box). Its methods on any value: `toString()`, `equals(Object)`, `hashCode()` (each dispatched on the value's class: a String compares by content, an `Integer` by value) and `getClass()`. `new Object()` makes an object with nothing but identity (`java.lang.Object@…`, equal only to itself). `wait
|
|
37
|
+
| **Inheritance** (`extends`, JLS 8.1.4) | Supported with limits | A class extends one class of the program: inherited fields and methods, overriding with dispatch on the object's class, `super(...)` (or the implicit `super()`), `super.f()` and `super.x`, covariant return types, field hiding, static methods inherited and hidden. Superclass constructors and field initializers run first, so a superclass constructor calling an overridden method sees the subclass's fields at their defaults, as on the JDK. `abstract` classes and methods, `final` classes and methods, `protected`. javac's errors: `B is not abstract and does not override abstract method f() in A`, `A is abstract; cannot be instantiated`, `cannot inherit from final A`, `f() in B cannot override f() in A` (with `overridden method is final`, `attempting to assign weaker access privileges; was public`, `return type long is not compatible with int`, `overriding method is static`), `cyclic inheritance involving A`, `abstract method f() in A cannot be accessed directly`, `x has private access in A` for a superclass's private member. NPE messages name the receiver's static type (`Cannot invoke "Main$B.f()"`), as the JDK does. A class may also extend the JDK's exception classes (*Exceptions* below) and its collections (*Library subclasses* below). javac's bridge methods (JLS 15.12.4.5) are reproduced: where an override's erasure differs from what it overrides (`compareTo(Box)` for `Comparable<Box>`, `Integer apply(Integer)` for `Function`, a covariant return type), a call through the supertype goes through a bridge, so a stack trace shows its frame at the class's line, and a raw call with a wrong argument is the bridge's `ClassCastException`. Extending other library classes, extending an inner (non-static) class, and statements before `super(...)` (Java 25's flexible constructor bodies) are unsupported. |
|
|
38
|
+
| **Interfaces** (JLS 9) | Supported with limits | Interfaces of the program, nested or top-level: abstract methods, `default` methods, `static` methods, `private` methods, constants; `extends` among interfaces; a class implementing several. Implementing methods must be `public` (`g() in C cannot implement g() in I`), and two unrelated defaults conflict (`types I and J are incompatible;`). A class may also implement the library's `Comparable<T>`, `Comparator<T>`, `Iterable<T>` and `Iterator<T>`: then sorting, `PriorityQueue`, `Collections.sort`, for-each and `Objects.compare` call its methods as Java code. Their other methods are its too, declared or not: `cmp.reversed()` of an abstract class implementing `Comparator`, `op.applyAsInt(2, 3)` of an enum whose constant bodies implement `IntBinaryOperator`. `Interface.super.f()` calls a direct superinterface's default method (JLS 15.12.3), also from an interface extending it and inside a lambda, with javac's errors: `not an enclosing class: I` (not a direct superinterface, or a static context), `bad type qualifier I in default super call` (`redundant interface I is extended by J`), `abstract method m() in I cannot be accessed directly`, `illegal static interface method call`. `Main.super.f()` in Main is `super.f()`; `Outer.super.f()` for an enclosing class and implementing other library interfaces are unsupported. |
|
|
39
|
+
| The `Object` type | Supported | Variables, parameters, fields, arrays (`Object[]`), returns. Any value converts to `Object` (primitives box). Its methods on any value: `toString()`, `equals(Object)`, `hashCode()` (each dispatched on the value's class: a String compares by content, an `Integer` by value) and `getClass()`. `new Object()` makes an object with nothing but identity (`java.lang.Object@…`, equal only to itself). `wait` and `notify` are unsupported, and so is `clone` except on arrays (below). |
|
|
40
40
|
| Casts and `instanceof` (JLS 15.16, 15.20.2) | Supported | Casts between classes, interfaces, library types and arrays, checked as javac checks them (`incompatible types: A cannot be converted to B` for impossible ones) and when they run: `ClassCastException: class Main$A cannot be cast to class Main$B (…)`, as the JDK words it. `(int) object` checks for an `Integer`, then unboxes. `x instanceof T`, raw types included (`x instanceof List`), and the type pattern `x instanceof T t`, whose variable is in scope where the test is true: in `&&`, the `if` or `while` body, after `if (!(x instanceof T t)) return;` (JLS 6.3.1). A store into an array seen through a supertype is checked: `ArrayStoreException: java.lang.String`. A cast the run cannot fully check (`(T) o`, `(T[]) new Object[n]`, `(List<Integer>) o`) checks the erasure and gives javac's `[unchecked] unchecked cast` warning (with `required:`, `found:` and a `where` clause); a cast between different parameterizations (`(List<String>) intList`) is javac's `incompatible types`. Record patterns: `o instanceof Line(Point(int a, int b), var to)`, their variables in scope as a type pattern's are. `instanceof` with a parameterized type (`x instanceof List<Integer>`) is unsupported. |
|
|
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
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. |
|
|
45
45
|
| 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 (`
|
|
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 (`LocalTime`, `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.LocalTime.of(...)` 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
47
|
| `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
48
|
| 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
49
|
| **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. |
|
|
@@ -65,12 +65,12 @@ Every feature has one status:
|
|
|
65
65
|
| Numeric promotion and conversions (JLS 5.1–5.6) | Supported | Widening in assignment, invocation, and operators (`int` + `long` is `long`, anything with `double` is `double`); casts in every direction with Java's rules (`(int) 1e300` saturates, `(int) NaN` is 0, `(char) 65601L` keeps the low bits); compound assignment's implicit cast (`long l = 5; l += 2.7;` is `7`); `possible lossy conversion from long to int`. Constant expressions fold with the same arithmetic. |
|
|
66
66
|
| `boolean` | Supported | |
|
|
67
67
|
| `String` | Supported with limits | Literals and text blocks (`"""`, JLS 3.10.6: the incidental indentation and trailing spaces are stripped, line ends become `\n`, and escapes, `\s` and the line-joining `\<newline>` included, are interpreted last; javac's `illegal text block open delimiter sequence, missing line terminator`, `unclosed text block`, `illegal escape character`), `null`, concatenation with any supported type, and `==` by reference (constants are interned). Methods: see the Library section; `new String(...)` makes a new object, so `new String("a") == "a"` is `false`. Contents are arbitrary Unicode (UTF-16). |
|
|
68
|
-
| Wrapper classes: `Integer`, `Long`, `Double`, `Character`, `Boolean` | Supported with limits | Boxing and unboxing (JLS 5.1.7–5.1.8) in assignment, invocation, operators, `?:`, compound assignment and `++`/`--`. `==` compares references, and the JDK's caches are reproduced (`Integer` and `Long` -128 to 127, `Character` 0 to 127, both `Boolean`s): `Integer a = 127, b = 127;` gives `a == b` true, and 128 gives false. Unboxing null is the JDK's NPE, `Cannot invoke "java.lang.Integer.intValue()" because …`. A switch on a wrapper is unsupported. |
|
|
68
|
+
| Wrapper classes: `Integer`, `Long`, `Double`, `Character`, `Boolean` | Supported with limits | Boxing and unboxing (JLS 5.1.7–5.1.8) in assignment, invocation, operators, `?:`, compound assignment and `++`/`--`. `==` compares references, and the JDK's caches are reproduced (`Integer` and `Long` -128 to 127, `Character` 0 to 127, both `Boolean`s): `Integer a = 127, b = 127;` gives `a == b` true, and 128 gives false. Unboxing null is the JDK's NPE, `Cannot invoke "java.lang.Integer.intValue()" because …`. The deprecated constructors (`new Integer(5)`, `new Double("3.5")`, and those of `Long`, `Float`, `Short`, `Byte`, `Character`, `Boolean`) make a new object every time, never a cached one, with javac's `[deprecation] Integer(int) in Integer has been deprecated` warnings. A switch on a wrapper is unsupported. |
|
|
69
69
|
| Generic types at use sites: `List<Integer>`, `Map<String, List<Integer>>`, `new ArrayList<>()` | Supported with limits | Type arguments are checked as javac checks them: invariance (`ArrayList<Integer> cannot be converted to List<String>`), `unexpected type` with `required: reference` for `List<int>`, and `wrong number of type arguments`. The diamond is inferred from the target type, the constructor's arguments, or the parameter it is passed to. Types print as javac prints them (`Map<String,Integer>`). Wildcards (`List<?>`, `List<? extends T>`, `Comparator<? super T>`) are supported: a value read through one has its bound's type, and a parameter of `? super T` takes a `T`. Generic array creation is javac's error, except of raw types (`new ArrayList[n]`, `new List[n]`) and unbounded wildcards (`new List<?>[n]`); a raw array assigned, returned or initialized as `List<Integer>[]` is javac's `[unchecked] unchecked conversion` warning. Raw types (`List raw = new ArrayList();`, `Map m`, `Box b = new Box("s")`, `(List) o`, `o instanceof List`) are supported: their members are erased (`raw.get(0)` is an `Object`), and javac's warnings are reported: `[unchecked] unchecked call to add(E) as a member of the raw type List`, `unchecked conversion` (raw to parameterized), `unchecked method invocation`, `unchecked assignment to variable v as member of raw type Box`, each with its `where` clause, and silenced by `@SuppressWarnings("unchecked")`. An argument that converts only unchecked makes the call `unchecked method invocation` and its type erased (`new ArrayList<>(raw)` is a raw `ArrayList`). As on the JDK, heap pollution through a raw type fails where the value is used (`int v = ints.get(0)` of a `String` is a `ClassCastException`). Generic calls are target-typed as javac types them: arguments bound a type variable from below (`List.of(1, 2.5)` is a `List<Number>`, `List.of(new Sq(1), new Circle(2))` a `List<Shape>` when both implement `Shape`), and an assignment, return or parameter that names the type argument decides it (`List<Shape> s = List.of(new Sq(1))`, `take(List.of(new Sq(1)))`), with javac's `inference variable E has incompatible bounds` when an argument does not fit. The engine has no intersection types: where javac infers one (`List.of(1, "a")` with no target), it keeps a common class or interface, or Object. |
|
|
70
70
|
| The program's classes as types | Supported | `Node n = new Node(1);`, parameters, return types, fields. `incompatible types: Bag cannot be converted to Box`, `incomparable types: Box and Bag`. |
|
|
71
|
-
| Arrays of any supported type, any number of dimensions | Supported | `new T[n]`, `new int[3][4]`, `new int[3][]` (jagged), `new T[]{…}`, nested `{{…}, {…}}` initializers, `a[i][j]`, and `.length`. Arrays are default-initialized, bounds-checked, and compared by reference. `int a[]` and `int[] a[]` declarations are accepted. They print with JVM descriptors: `[[I@hash`, `[J@hash`, `[LNode;@hash`. |
|
|
71
|
+
| Arrays of any supported type, any number of dimensions | Supported | `new T[n]`, `new int[3][4]`, `new int[3][]` (jagged), `new T[]{…}`, nested `{{…}, {…}}` initializers, `a[i][j]`, and `.length`. Arrays are default-initialized, bounds-checked, and compared by reference. `int a[]` and `int[] a[]` declarations are accepted. They print with JVM descriptors: `[[I@hash`, `[J@hash`, `[LNode;@hash`. `a.clone()` is a shallow copy of the same type (`int[][]`'s rows are shared), as on the JDK. |
|
|
72
72
|
| Casts between `int` and `char`, and identity casts | Supported | `(char) 65601` keeps the low 16 bits. A cast from boolean to int is an error, as in Java. |
|
|
73
|
-
| `var` (JLS 14.4.1) | Supported | For locals, `for` and enhanced-`for` variables and resources: the type of the initializer (a diamond nothing decides is `Object`'s, `new ArrayList<>()` an `ArrayList<Object>`). javac's errors: `cannot infer type for local variable x` with `(variable initializer is 'null')`, `(lambda expression needs an explicit target-type)`, `(method reference needs an explicit target-type)`, `(array initializer needs an explicit target-type)`, `(cannot use 'var' on variable without initializer)` and `(cannot use 'var' on self-referencing variable)`; `'var' is not allowed in a compound declaration`, `… as an element type of an array`, and `'var' is not allowed here` for a field. `var` lambda parameters
|
|
73
|
+
| `var` (JLS 14.4.1) | Supported | For locals, `for` and enhanced-`for` variables and resources: the type of the initializer (a diamond nothing decides is `Object`'s, `new ArrayList<>()` an `ArrayList<Object>`). javac's errors: `cannot infer type for local variable x` with `(variable initializer is 'null')`, `(lambda expression needs an explicit target-type)`, `(method reference needs an explicit target-type)`, `(array initializer needs an explicit target-type)`, `(cannot use 'var' on variable without initializer)` and `(cannot use 'var' on self-referencing variable)`; `'var' is not allowed in a compound declaration`, `… as an element type of an array`, and `'var' is not allowed here` for a field. `var` lambda parameters (`(var a, var b) -> a + b`, also with `final`), with javac's `invalid lambda parameter declaration` and its `(cannot mix 'var' and explicitly-typed parameters)` / `(cannot mix 'var' and implicitly-typed parameters)` details. |
|
|
74
74
|
| `float` (JLS 4.2.3) | Supported | IEEE 754 binary32, as Java: every operation is the double one rounded once to float (exact for `+ - * / %`), and `long` → `float` rounds once (`(float) 9007199254740993L` is `9.007199E15`). Literals with `f`/`F`, decimal or hexadecimal, rounded once and correctly (`1.0000000596046447753906250001f` is `1.0000001`), with `floating-point number too large` / `too small`. Printed as JDK 19+'s `Float.toString` (the shortest decimal that rounds back, computed exactly: 3,000 random floats print as on JDK 25). Promotion, widening and javac's `possible lossy conversion from double to float` as JLS 5.1–5.6 say; `Math.abs`, `max`, `min`, `round` (an `int`), `signum`, `ulp`, `nextUp`, `nextDown`, `clamp` of floats; `float[]`. A `switch` on a float is javac's `primitive patterns are a preview feature`. |
|
|
75
75
|
| `byte`, `short` (JLS 4.2.1) | Supported | Promoted to `int` in arithmetic; `b += 120` and `b++` narrow back, wrapping as Java does; `(byte) 300.5f` goes through `int`. A constant that fits may be assigned without a cast (`byte b = 10;`, `short s = 'B';`, `Byte b = 100;`), others are javac's `possible lossy conversion from int to byte`. `byte[]`, `short[]`, `switch` on either (a label out of range is a lossy-conversion error), and JLS 15.25's conditional typing (`byte` with `short` is `short`). |
|
|
76
76
|
|
|
@@ -110,46 +110,51 @@ Every feature has one status:
|
|
|
110
110
|
| `java.io.PrintWriter`, `BufferedWriter`, `OutputStreamWriter`, `StringWriter` | Supported | Over `System.out`, `System.err`, each other, or a `StringWriter`: every `print`/`println` overload, `printf`, `format`, `write`, `append`, `newLine`, `flush`, `close`, `checkError`, autoflush. They buffer as the JDK's do (ADR 0016): what is not flushed when the program ends is lost, and exactly the part the JDK writes out reaches the output (4,000 unflushed lines print their first 24,576 bytes). `PrintWriter` never throws `IOException`; the others do, after `close`. File names and charsets are unsupported, as is `StringWriter.getBuffer()`. |
|
|
111
111
|
| `java.util.StringTokenizer` | Supported | `hasMoreTokens`, `nextToken`, `nextToken(delimiters)`, `hasMoreElements`, `nextElement`, `countTokens`; the default delimiters `" \t\n\r\f"`, custom ones, and returning delimiters as tokens. `NoSuchElementException` at the end; the JDK's `NullPointerException`s for a null string or delimiters. |
|
|
112
112
|
| `java.io.StreamTokenizer` | Supported with limits | `nextToken`, the public fields `ttype`, `nval` and `sval`, `TT_EOF`, `TT_EOL`, `TT_NUMBER`, `TT_WORD`, `pushBack`, `lineno`, `toString`, and the syntax methods (`wordChars`, `whitespaceChars`, `ordinaryChar(s)`, `commentChar`, `quoteChar`, `parseNumbers`, `resetSyntax`, `eolIsSignificant`, `lowerCaseMode`). Numbers have the JDK's exact values, including its rounding of long digit strings. `slashStarComments` and `slashSlashComments` are unsupported. |
|
|
113
|
-
| `System.out` / `System.err`: `print` and `println` | Supported | Overloads are resolved as in javac across all nine (`println` also has a no-argument form): `println('x')` prints the char, `println(charArray)` prints the characters, and other arrays print as `type@hash`. `println(null)` is ambiguous, as in Java. |
|
|
113
|
+
| `System.out` / `System.err`: `print` and `println` | Supported | Overloads are resolved as in javac across all nine (`println` also has a no-argument form): `println('x')` prints the char, `println(charArray)` prints the characters, and other arrays print as `type@hash`. `println(null)` is ambiguous, as in Java, and so is a generic call whose result only an implicit lambda or an inexact method reference decides (`println(stream.collect(collectingAndThen(toList(), l -> …)))`: such arguments do not count for applicability, JLS 15.12.2.2), with javac's two errors. |
|
|
114
114
|
| `System.out` / `System.err` as values; `flush()`, `close()`, `checkError()` | Supported | Passed to `PrintWriter` or `OutputStreamWriter` as the `OutputStream` they are. `System.out` prints at once, so `flush()` has nothing to do. Closing it, directly or through a writer over it, drops everything printed to it afterwards, as on the JDK; a closed `System.err` drops an uncaught exception's trace too. `PrintStream` as a declared type, `write` and `append` are unsupported. |
|
|
115
115
|
| `System.out` / `System.err`: `printf(String, Object...)`, `format(String, Object...)` | Supported with limits | As `String.format`, below. The call is a statement: the `PrintStream` it returns cannot be used (`System.out.printf(...).println()` is unsupported). The `Locale` overloads are unsupported. |
|
|
116
116
|
| `String.length()`, `charAt(int)`, `equals(Object)`, `isEmpty()`, `toCharArray()`, `compareTo(String)` | Supported | `equals` boxes primitives, so `"x".equals(5)` is `false`, as in Java. `compareTo` gives the JDK's values (the first differing character's difference, else the length difference) and its NPE messages. These need no Java library. |
|
|
117
|
-
| Other `String` methods | Supported | `substring`, `indexOf` and `lastIndexOf` (of a `String` or a character, from an index), `contains`, `startsWith`, `endsWith`, `toUpperCase`, `toLowerCase`, `trim`, `strip`, `stripLeading`, `stripTrailing`, `isBlank`, `repeat`, `lines` (a `Stream<String>`, lines ended by `\n`, `\r` or `\r\n`), `stripIndent`, `translateEscapes` (`Invalid escape sequence: \q \\u0071`), `indent`, `replace` (chars or strings), `equalsIgnoreCase`, `compareToIgnoreCase`, `concat`, `hashCode`, `toString`, `split` (with and without a limit), `replaceAll`, `replaceFirst`, `matches`, `formatted`; statics `valueOf` (every supported type, `char[]` and a range of one), `copyValueOf`, `format`, `join` (varargs, an array, or an `Iterable` such as a `List<String>`); constructors `()`, `(String)`, `(char[])`, `(char[], int, int)`, `(StringBuilder)`. The JDK's exceptions and NPE messages: `Range [4, 3) out of bounds for length 3` (from `"abc".substring(4)`), `Range [1, 1 + 5) out of bounds for length 2`, `count is negative: -1`, `Cannot invoke "String.isEmpty()" because "this.pattern" is null`. `split` follows Java's rules (no leading empty string from a zero-width match, trailing empty strings removed when the limit is 0). Case mapping is the JDK's root-locale mapping (`"straße".toUpperCase()` is `STRASSE`). Parameters the JDK declares as `CharSequence` take a `String` here. `intern()` returns the run's one String of that value, the same object as an equal literal. `chars`, `
|
|
118
|
-
| Regular expressions (`split`, `replaceAll`, `replaceFirst`, `matches`) | Supported with limits | Java's syntax, translated to JavaScript's engine with Java's meanings: `.` and `$` know Java's line terminators (including `\r\n` and U+0085), `\s` is ASCII whitespace, `\h`, `\v`, `\R`, `\A`, `\z`, `\Z`, `\Q…\E`, POSIX classes (`\p{Alpha}`, `\p{Upper}`, …), named groups and back references, a leading `(?i)` or `(?s)`. Replacements as Java reads them: `$1`, `${name}`, `\$`, with `IllegalArgumentException: Illegal group reference` and `No group 2`. Malformed patterns are `PatternSyntaxException` with the JDK's description, index and caret (`Unclosed group near index 1`, `Dangling meta character '*' near index 0`). Constructs that do not translate exactly are engine limitations (below). `java.util.regex.
|
|
117
|
+
| Other `String` methods | Supported | `substring`, `indexOf` and `lastIndexOf` (of a `String` or a character, from an index), `contains`, `startsWith`, `endsWith`, `toUpperCase`, `toLowerCase`, `trim`, `strip`, `stripLeading`, `stripTrailing`, `isBlank`, `repeat`, `lines` (a `Stream<String>`, lines ended by `\n`, `\r` or `\r\n`), `stripIndent`, `translateEscapes` (`Invalid escape sequence: \q \\u0071`), `indent`, `replace` (chars or strings), `equalsIgnoreCase`, `compareToIgnoreCase`, `concat`, `hashCode`, `toString`, `split` (with and without a limit), `replaceAll`, `replaceFirst`, `matches`, `formatted`; statics `valueOf` (every supported type, `char[]` and a range of one), `copyValueOf`, `format`, `join` (varargs, an array, or an `Iterable` such as a `List<String>`); constructors `()`, `(String)`, `(char[])`, `(char[], int, int)`, `(StringBuilder)`. The JDK's exceptions and NPE messages: `Range [4, 3) out of bounds for length 3` (from `"abc".substring(4)`), `Range [1, 1 + 5) out of bounds for length 2`, `count is negative: -1`, `Cannot invoke "String.isEmpty()" because "this.pattern" is null`. `split` follows Java's rules (no leading empty string from a zero-width match, trailing empty strings removed when the limit is 0). Case mapping is the JDK's root-locale mapping (`"straße".toUpperCase()` is `STRASSE`). Parameters the JDK declares as `CharSequence` take a `String` here. `intern()` returns the run's one String of that value, the same object as an equal literal. `String.CASE_INSENSITIVE_ORDER` (exact for Latin-1). `chars()` (an `IntStream`), `codePointAt` (`Index 5 out of bounds for length 3`), `getBytes()` (UTF-8, a lone surrogate encoded as `?`), `transform`. `getBytes(String)` and the other charset forms, `codePoints`, `regionMatches`, `contentEquals`, `subSequence` and the rest are unsupported. |
|
|
118
|
+
| Regular expressions (`split`, `replaceAll`, `replaceFirst`, `matches`, `java.util.regex`) | Supported with limits | Java's syntax, translated to JavaScript's engine with Java's meanings: `.` and `$` know Java's line terminators (including `\r\n` and U+0085), `\s` is ASCII whitespace, `\h`, `\v`, `\R`, `\A`, `\z`, `\Z`, `\Q…\E`, POSIX classes (`\p{Alpha}`, `\p{Upper}`, …), named groups and back references, a leading `(?i)` or `(?s)`. Replacements as Java reads them: `$1`, `${name}`, `\$`, with `IllegalArgumentException: Illegal group reference` and `No group 2`. Malformed patterns are `PatternSyntaxException` with the JDK's description, index and caret (`Unclosed group near index 1`, `Dangling meta character '*' near index 0`). Constructs that do not translate exactly are engine limitations (below). **`Pattern` and `Matcher`:** `Pattern.compile` (with `CASE_INSENSITIVE`, `LITERAL` and `DOTALL`; the other flags are limitations), `matches`, `quote`, `matcher`, `split`, `pattern`, `flags`; `find` (after an empty match, one character further on, as the JDK's), `find(int)`, `matches`, `lookingAt`, `group`, `start` and `end` by number and by name, `groupCount`, `reset`, `replaceAll` (a String or a `Function<MatchResult, String>`), `replaceFirst`, `appendReplacement` and `appendTail`, `results()`, `toMatchResult()`, `toString` (`java.util.regex.Matcher[pattern=z region=0,3 lastmatch=]`), with the JDK's `No match found`, `No group 3`, `No group with name <x>`, `Illegal start index`. Regions, `hitEnd`, `usePattern`, `asPredicate` and `PatternSyntaxException`'s `getIndex` and friends are unsupported. |
|
|
119
119
|
| `String.format`, `formatted` | Supported with limits | Conversions `%d %o %x %X %s %S %c %C %b %B %h %H %e %E %f %g %G %n %%`, with argument indexes (`%2$s`, `%<s`), flags (`-#+ 0,(`), width and precision. Floating point rounds as Java's Formatter does, half-up on the shortest decimal: `%.2f` of `1.005` is `1.01` (C's printf gives `1.00`). The JDK's exceptions: `IllegalFormatConversionException: d != java.lang.String`, `MissingFormatArgumentException: Format specifier '%d'`, `UnknownFormatConversionException: Conversion = 'q'`, `FormatFlagsConversionMismatchException`, and others. Date and time (`%t`) and hexadecimal floating point (`%a`) are engine limitations; the `Locale` overloads are unsupported. |
|
|
120
120
|
| `Math.abs`, `max`, `min` (int, long, double), `sqrt`, `floor`, `ceil`, `round(double)`, `Math.PI`, `Math.E` | Supported | Resolved against all of Math's overloads, so `Math.max(1, 2L)` is the long one and errors list every candidate as javac does. `Math.abs(Integer.MIN_VALUE)` is `MIN_VALUE`; `Math.round` rounds half up and saturates. These need no Java library. |
|
|
121
|
-
| Other `Math` methods | Supported with limits | `pow`, `exp`, `log`, `log10`, `sin`, `cos`, `tan`, `asin`, `acos`, `atan`, `atan2`, `sinh`, `cosh`, `tanh`, `cbrt`, `hypot`, `expm1`, `log1p`, `toRadians`, `toDegrees`, `signum`, `rint`, `ulp`, `nextUp`, `nextDown`, `random`; exact integer arithmetic (`addExact`, `subtractExact`, `multiplyExact`, `incrementExact`, `decrementExact`, `negateExact`, `toIntExact`, `absExact`) with `ArithmeticException: integer overflow` / `long overflow`; `floorDiv`, `floorMod` (`/ by zero`); `clamp` (`IllegalArgumentException: 5 > 2`). The transcendental functions may differ from the JDK in the last digit (see Known divergences). Their float overloads too. `fma`, `copySign`, `scalb`, `
|
|
121
|
+
| Other `Math` methods | Supported with limits | `pow`, `exp`, `log`, `log10`, `sin`, `cos`, `tan`, `asin`, `acos`, `atan`, `atan2`, `sinh`, `cosh`, `tanh`, `cbrt`, `hypot`, `expm1`, `log1p`, `toRadians`, `toDegrees`, `signum`, `rint`, `ulp`, `nextUp`, `nextDown`, `random`; exact integer arithmetic (`addExact`, `subtractExact`, `multiplyExact`, `incrementExact`, `decrementExact`, `negateExact`, `toIntExact`, `absExact`) with `ArithmeticException: integer overflow` / `long overflow`; `floorDiv`, `floorMod` (`/ by zero`); `clamp` (`IllegalArgumentException: 5 > 2`). The transcendental functions may differ from the JDK in the last digit (see Known divergences). Their float overloads too. `ceilDiv` and `ceilMod` (int, long, and long with int). `fma`, `copySign`, `scalb`, `divideExact`, `ceilDivExact` and the rest are unsupported. |
|
|
122
122
|
| `System` methods | Supported | `currentTimeMillis`, `nanoTime`, `exit`, `arraycopy`, `lineSeparator` (`"\n"`), `identityHashCode`. `System.exit(n)` ends the run at once and prints nothing, as the JDK does; the run's exit code is `n` (status `exited` when `n` is not 0, `success` when it is). `arraycopy` has the JDK's checks and messages: `arraycopy: last source index 8 out of bounds for int[5]`, `arraycopy: type mismatch: can not copy int[] into long[]`, and overlapping copies within one array. `getProperty`, `getenv`, `setOut` and the others are unsupported. |
|
|
123
123
|
| `java.util.Objects` | Supported | `equals`, `hash` (`Arrays.hashCode` of its arguments, calling their `hashCode()`), `hashCode`, `toString` (with a default), `isNull`, `nonNull`, `requireNonNull` (with a message), `requireNonNullElse`, `checkIndex` (`Index 5 out of bounds for length 3`), `compare` with a comparator. |
|
|
124
124
|
| `java.util.Random` | Supported with limits | `nextInt()`, `nextInt(bound)`, `nextInt(origin, bound)`, `nextLong()` (and its bounded forms), `nextDouble()` (and its bounded forms), `nextBoolean`, `nextGaussian()`, `setSeed`; constructors `()` and `(long seed)`. A seeded generator produces exactly the JDK's sequence (the 48-bit generator the API documentation specifies). An unseeded one, like `Math.random()`, is unpredictable, as on the JDK. `nextFloat()`. The `ints`/`doubles` streams and `nextGaussian(mean, stddev)` are unsupported. |
|
|
125
|
-
| `Integer.MAX_VALUE`/`MIN_VALUE`/`SIZE`/`BYTES`, `Long.MAX_VALUE`/`MIN_VALUE`/`SIZE`/`BYTES`, `Character.MAX_VALUE`/`MIN_VALUE`/`MIN_RADIX`/`MAX_RADIX`/`SIZE`/`BYTES`, `Double.MAX_VALUE`/`MIN_VALUE`/`MIN_NORMAL`/`POSITIVE_INFINITY`/`NEGATIVE_INFINITY`/`NaN`/`SIZE`/`BYTES` | Supported | Constants, folded like any constant. Using one does not load the Java library. |
|
|
126
|
-
| `ArrayList`, `List` | Supported | `add(E)`, `add(int, E)`, `get`, `set`, `remove(int)`, `remove(Object)`, `size`, `isEmpty`, `contains`, `indexOf`, `lastIndexOf`, `clear`, `addAll`, `containsAll`, `iterator`, `getFirst`, `getLast`, `removeFirst`, `removeLast`, `addFirst`, `addLast`, `sort(Comparator)` (natural order for null; it counts as a change, so sorting inside a for-each over the list is a `ConcurrentModificationException`), `subList` (a view: changes go through to the list and back, a structural change to the list makes the view throw `ConcurrentModificationException`, the JDK's range messages `fromIndex = -1`, `toIndex = 4`, `fromIndex(2) > toIndex(1)`; on every list kind, with the JDK's class names, `ArrayList$SubList`, `AbstractList$SubList` for `LinkedList`, `ImmutableCollections$SubList` for `List.of`, `AbstractList$RandomAccessSubList` for `Arrays.asList`), `equals`, `hashCode`, `toString`. Constructors `()`, `(int)`, `(Collection)`. Overload resolution decides as javac does: `list.remove(1)` removes at an index, `list.remove(Integer.valueOf(1))` removes an element. The JDK's exceptions: `Index 5 out of bounds for length 1`, `Index: 3, Size: 2` from `add(int, E)`, `Illegal Capacity: -1`. The iterator fails fast exactly as the JDK's does: removing the second-to-last element during for-each does not throw. |
|
|
125
|
+
| `Integer.MAX_VALUE`/`MIN_VALUE`/`SIZE`/`BYTES`, `Long.MAX_VALUE`/`MIN_VALUE`/`SIZE`/`BYTES`, `Character.MAX_VALUE`/`MIN_VALUE`/`MIN_RADIX`/`MAX_RADIX`/`SIZE`/`BYTES`, `Double.MAX_VALUE`/`MIN_VALUE`/`MIN_NORMAL`/`POSITIVE_INFINITY`/`NEGATIVE_INFINITY`/`NaN`/`SIZE`/`BYTES` | Supported | Constants, folded like any constant. Using one does not load the Java library. `Boolean.TRUE` and `Boolean.FALSE` are the cached `Boolean`s (`Boolean.TRUE == Boolean.valueOf(true)`). |
|
|
126
|
+
| `ArrayList`, `List` | Supported | `add(E)`, `add(int, E)`, `get`, `set`, `remove(int)`, `remove(Object)`, `size`, `isEmpty`, `contains`, `indexOf`, `lastIndexOf`, `clear`, `addAll`, `containsAll`, `removeAll`, `retainAll`, `iterator`, `listIterator` (from the start or an index: both directions, `nextIndex`/`previousIndex`, `set`, `add`, `remove`, failing fast as the JDK's), `getFirst`, `getLast`, `removeFirst`, `removeLast`, `addFirst`, `addLast`, `reversed()` (a live reverse-ordered view, `java.util.ReverseOrderListView`, whose changes go through), `sort(Comparator)` (natural order for null; it counts as a change, so sorting inside a for-each over the list is a `ConcurrentModificationException`), `subList` (a view: changes go through to the list and back, a structural change to the list makes the view throw `ConcurrentModificationException`, the JDK's range messages `fromIndex = -1`, `toIndex = 4`, `fromIndex(2) > toIndex(1)`; on every list kind, with the JDK's class names, `ArrayList$SubList`, `AbstractList$SubList` for `LinkedList`, `ImmutableCollections$SubList` for `List.of`, `AbstractList$RandomAccessSubList` for `Arrays.asList`), `equals`, `hashCode`, `toString`. Constructors `()`, `(int)`, `(Collection)`. Overload resolution decides as javac does: `list.remove(1)` removes at an index, `list.remove(Integer.valueOf(1))` removes an element. The JDK's exceptions: `Index 5 out of bounds for length 1`, `Index: 3, Size: 2` from `add(int, E)`, `Illegal Capacity: -1`. The iterator fails fast exactly as the JDK's does: removing the second-to-last element during for-each does not throw. |
|
|
127
127
|
| `TreeMap`, `SortedMap`, `NavigableMap` | Supported | Natural order or a `Comparator`: `put`, `get`, `getOrDefault`, `putIfAbsent`, `containsKey`, `containsValue`, `remove` (both forms), `replace`, `putAll`, `size`, `isEmpty`, `clear`, `firstKey`, `lastKey`, `floorKey`, `ceilingKey`, `lowerKey`, `higherKey` and their `…Entry` forms, `firstEntry`, `lastEntry`, `pollFirstEntry`, `pollLastEntry`, `comparator`, `keySet`, `navigableKeySet`, `descendingKeySet`, `values`, `entrySet`, `equals`, `hashCode`, `toString`. The live range views `headMap`, `tailMap`, `subMap` (with or without inclusive bounds) and `descendingMap`, as deep as wanted, with the JDK's `key out of range`, `fromKey out of range`, `toKey out of range` and `fromKey > toKey`. Constructors `()`, `(Comparator)`, `(Map)`, `(SortedMap)` (which keeps the comparator). The JDK's exceptions: `ClassCastException` for keys that are not Comparable or not mutually comparable, `NullPointerException` for a null key in natural order (`Cannot invoke "java.lang.Comparable.compareTo(Object)" because "k1" is null` when the map is empty), `NoSuchElementException` from `firstKey` of an empty map, `UnsupportedOperationException` from `setValue` on `firstEntry()`'s snapshot. Iterators fail fast as the JDK's do, and removing through one continues correctly. `comparator()` of a descending view is an engine limitation. |
|
|
128
|
-
| `TreeSet`, `SortedSet`, `NavigableSet` | Supported | `add`, `remove`, `contains`, `size`, `isEmpty`, `clear`, `first`, `last`, `floor`, `ceiling`, `lower`, `higher`, `pollFirst`, `pollLast`, `iterator`, `descendingIterator`, `comparator`, `headSet`, `tailSet`, `subSet` (live views, with or without inclusive bounds), `descendingSet`, `addAll`, `containsAll`, `toArray`, `equals`, `hashCode`, `toString`. Constructors `()`, `(Comparator)`, `(Collection)`, `(SortedSet)` (which keeps the comparator). Exceptions as for `TreeMap`. |
|
|
129
|
-
| `LinkedList` | Supported | A `List` and a `Deque`: every `ArrayList` method above, and `offer`, `offerFirst`, `offerLast`, `push`, `pop`, `poll`, `pollFirst`, `pollLast`, `peek`, `peekFirst`, `peekLast`, `element`, `remove()`, `removeFirstOccurrence`, `removeLastOccurrence`, `descendingIterator
|
|
130
|
-
| `Stack` | Supported | `push`, `pop`, `peek` (`EmptyStackException` when empty), `empty`, `search`,
|
|
131
|
-
| `ArrayDeque`, `Deque`, `Queue` | Supported with limits | Both ends (`addFirst`/`addLast`, `offerFirst`/`offerLast`, `pollFirst`/`pollLast`, `peekFirst`/`peekLast`, `getFirst`/`getLast`, `removeFirst`/`removeLast`), as a stack (`push`, `pop`, `peek`) and a queue (`offer`, `poll`, `peek`, `element`, `remove()`, `add`). Also `contains`, `remove(Object)`, `removeFirstOccurrence`, `removeLastOccurrence`, `size`, `isEmpty`, `clear`, `iterator`, `descendingIterator`, `addAll`, `toString`. Constructors `()`, `(int)`, `(Collection)`. Null elements are an NPE, and an empty deque's `pop()` is `NoSuchElementException`, as in the JDK. Changing a deque while iterating over it is an engine limitation. |
|
|
132
|
-
| `PriorityQueue` | Supported with limits | Natural order or a `Comparator`: `offer`, `add`, `poll`, `peek`, `element`, `remove()`, `remove(Object)`, `contains`, `size`, `isEmpty`, `clear`, `iterator`, `addAll`, `toString`. Constructors `()`, `(int)`, `(Comparator)`, `(int, Comparator)`, `(Collection)` (a priority queue is copied with its comparator). The heap is laid out as the JDK lays it out, so it prints in the same order (`[1, 3, 2, 5, 9, 8, 7]`). Elements are `String`, `StringBuilder` or wrapper values; the JDK's `ClassCastException` for arrays and library objects is reproduced. In natural order, objects of the program's own classes are an engine limitation; give the queue a comparator for them. |
|
|
133
|
-
| `HashMap`, `Map`, `LinkedHashMap` | Supported with limits | `get`, `put`, `getOrDefault`, `putIfAbsent`, `containsKey`, `containsValue`, `remove(Object)`, `remove(key, value)`, `replace` (both forms), `putAll`, `size`, `isEmpty`, `clear`, `keySet`, `values`, `entrySet`, `equals`, `hashCode`, `toString`. Constructors `()`, `(int)`, `(Map)`. **Iteration order is the JDK's:** the table is laid out as JDK 25 lays it out (power-of-two buckets, the spread hash, chains appended in order, doubling at three quarters full with each chain split in order, a bucket of 9 or more colliding keys turned into a red-black tree whose root comes first), so a map prints and iterates as on the JDK, `{over=1, mat=1, a=1, quick=1, …}`. `LinkedHashMap` iterates in insertion order. The views write through: `keySet().remove`, `values().remove`, an iterator's `remove`, and `Map.Entry.setValue`. Their iterators fail fast exactly as the JDK's: removing the last key during for-each does not throw, adding one does. Lookups are exact: `Integer` 1 and `Long` 1 are different keys, and so are `0.0` and `-0.0`. Null keys and values work, and a key's declared `hashCode()` runs where the JDK runs it. Where the JDK's order cannot be known, iterating is an engine limitation (below). `merge`, `compute…`, `forEach` and the other
|
|
128
|
+
| `TreeSet`, `SortedSet`, `NavigableSet` | Supported | `add`, `remove`, `contains`, `size`, `isEmpty`, `clear`, `first`, `last`, `floor`, `ceiling`, `lower`, `higher`, `pollFirst`, `pollLast`, `iterator`, `descendingIterator`, `comparator`, `reversed()` (its `descendingSet()`), `headSet`, `tailSet`, `subSet` (live views, with or without inclusive bounds), `descendingSet`, `addAll`, `containsAll`, `toArray`, `equals`, `hashCode`, `toString`. Constructors `()`, `(Comparator)`, `(Collection)`, `(SortedSet)` (which keeps the comparator). Exceptions as for `TreeMap`. |
|
|
129
|
+
| `LinkedList` | Supported | A `List` and a `Deque`: every `ArrayList` method above, and `offer`, `offerFirst`, `offerLast`, `push`, `pop`, `poll`, `pollFirst`, `pollLast`, `peek`, `peekFirst`, `peekLast`, `element`, `remove()`, `removeFirstOccurrence`, `removeLastOccurrence`, `descendingIterator`, `reversed()` (a live view that is a `List` and a `Deque`). Null elements are allowed. Messages as the JDK's: `Index: 7, Size: 3` for an index out of range, `NoSuchElementException` from `getFirst`, `removeFirst`, `pop` or `element` on an empty list (`peek` and `poll` return null). Iteration fails fast as `ArrayList`'s does, and `sort` is not a structural change, so sorting during for-each does not throw. |
|
|
130
|
+
| `Vector`, `Stack`, `Enumeration` | Supported | `Vector`: every `List` method, constructors `()`, `(int)` (`Illegal Capacity: -1`), `(int, int)` (a capacity increment) and `(Collection)`, `elements()` (an `Enumeration` that reads the vector as it is, `NoSuchElementException: Vector Enumeration` past the end), `setSize`, `trimToSize`, `ensureCapacity`. `Stack`: `push`, `pop`, `peek` (`EmptyStackException` when empty), `empty`, `search`, and Vector's `elementAt`, `setElementAt`, `insertElementAt`, `removeElementAt`, `addElement`, `removeElement`, `removeAllElements`, `firstElement`, `lastElement`, `capacity`. Its capacity starts at 10 and grows by the increment or doubles, and shows in its messages: `Array index out of range: 5`, `Index -1 out of bounds for length 10`, `5 >= 2`, `5 > 2`. |
|
|
131
|
+
| `ArrayDeque`, `Deque`, `Queue` | Supported with limits | Both ends (`addFirst`/`addLast`, `offerFirst`/`offerLast`, `pollFirst`/`pollLast`, `peekFirst`/`peekLast`, `getFirst`/`getLast`, `removeFirst`/`removeLast`), as a stack (`push`, `pop`, `peek`) and a queue (`offer`, `poll`, `peek`, `element`, `remove()`, `add`). Also `contains`, `remove(Object)`, `removeFirstOccurrence`, `removeLastOccurrence`, `size`, `isEmpty`, `clear`, `iterator`, `descendingIterator`, `addAll`, `removeAll`, `retainAll`, `reversed()` (a live view), `toString`. Constructors `()`, `(int)`, `(Collection)`. Null elements are an NPE, and an empty deque's `pop()` is `NoSuchElementException`, as in the JDK. Changing a deque while iterating over it is an engine limitation. |
|
|
132
|
+
| `PriorityQueue` | Supported with limits | Natural order or a `Comparator`: `offer`, `add`, `poll`, `peek`, `element`, `remove()`, `remove(Object)`, `contains`, `size`, `isEmpty`, `clear`, `iterator`, `addAll`, `removeAll`, `retainAll` (the survivors re-heapified as the JDK does), `toString`. Constructors `()`, `(int)`, `(Comparator)`, `(int, Comparator)`, `(Collection)` (a priority queue is copied with its comparator). The heap is laid out as the JDK lays it out, so it prints in the same order (`[1, 3, 2, 5, 9, 8, 7]`). Elements are `String`, `StringBuilder` or wrapper values; the JDK's `ClassCastException` for arrays and library objects is reproduced. In natural order, objects of the program's own classes are an engine limitation; give the queue a comparator for them. |
|
|
133
|
+
| `HashMap`, `Map`, `LinkedHashMap` | Supported with limits | `get`, `put`, `getOrDefault`, `putIfAbsent`, `containsKey`, `containsValue`, `remove(Object)`, `remove(key, value)`, `replace` (both forms), `putAll`, `size`, `isEmpty`, `clear`, `keySet`, `values`, `entrySet`, `equals`, `hashCode`, `toString`. Constructors `()`, `(int)`, `(int, float)` (`Illegal initial capacity: -1`, `Illegal load factor: 0.0`), `(Map)`, and `LinkedHashMap(int, float, boolean)`. **Iteration order is the JDK's:** the table is laid out as JDK 25 lays it out (power-of-two buckets, the spread hash, chains appended in order, doubling at three quarters full with each chain split in order, a bucket of 9 or more colliding keys turned into a red-black tree whose root comes first), so a map prints and iterates as on the JDK, `{over=1, mat=1, a=1, quick=1, …}`. `LinkedHashMap` iterates in insertion order, or, made with `accessOrder` true, in access order: `get`, `getOrDefault`, `put` of an existing key and the other reads move an entry to the end, a structural change as on the JDK (a `get` while iterating is a `ConcurrentModificationException`). A load factor sizes the table as the JDK's does, and a copy (`new HashMap<>(map)`, `putAll`) is sized as JDK 25 sizes it. The views write through: `keySet().remove`, `values().remove`, an iterator's `remove`, and `Map.Entry.setValue`. Their iterators fail fast exactly as the JDK's: removing the last key during for-each does not throw, adding one does. Lookups are exact: `Integer` 1 and `Long` 1 are different keys, and so are `0.0` and `-0.0`. Null keys and values work, and a key's declared `hashCode()` runs where the JDK runs it. Where the JDK's order cannot be known, iterating is an engine limitation (below). The lambda-taking methods (`merge`, `compute…`, `forEach`) are under *Higher-order collection methods*. A subclass's `removeEldestEntry` is under *Library subclasses*. `LinkedHashMap`'s `reversed()` and the other sequenced views, and `putFirst`/`putLast`, are unsupported. |
|
|
134
|
+
| **Library subclasses** (ADR 0023) | Supported with limits | A class may extend `ArrayList`, `LinkedList`, `HashMap`, `LinkedHashMap`, `TreeMap`, `HashSet`, `LinkedHashSet`, `TreeSet`, `ArrayDeque` or `PriorityQueue`, named, anonymous or generic (`class Bag<T> extends ArrayList<T>`, `new HashMap<>() {{ put("a", 1); }}`), and a program class may extend such a class in turn. It has its own fields, constructors (`super(16, 0.75f, true)`, or the implicit `super()`), and methods; it calls the inherited ones by simple name (`size()`, `merge(k, 1, Integer::sum)`), through `super.`, or from outside; it is an `instanceof` its library types and goes wherever they are expected (for-each, `new TreeMap<>(counter)`, `Collections.sort(this)`); it prints, compares and hashes as its library class does unless it overrides `toString`, `equals` or `hashCode`. **Overriding:** `LinkedHashMap.removeEldestEntry`, which the map asks after `put`, `putIfAbsent`, `putAll` (per mapping), `computeIfAbsent`, `compute` and `merge` add a mapping, as the JDK's does (an LRU cache: `super(capacity, 0.75f, true)` and `size() > capacity`); `ArrayList.add(E)`, `get(int)` and `size()`; `HashMap`'s and `LinkedHashMap`'s `put`, `get`, `containsKey` and `remove(Object)`; `TreeMap`'s `get` and `containsKey`. These are methods the JDK's own code in that class does not call on the object, so the rest of the class behaves the same. Overriding other library methods is unsupported (`overriding ArrayList.remove(int) is not supported in this version`). Where a library method given the object would call one of its overrides on the JDK (`Collections.addAll` calls `add`, a `Map`'s `equals` calls `get`, `Collections.unmodifiableList` calls everything), that call is an engine limitation rather than running without the override. `removeEldestEntry` is protected: javac's `has protected access` from other code. **`AbstractList`** (ADR 0025): a subclass implements `get` and `size` (javac's `is not abstract and does not override abstract method size() in AbstractCollection` otherwise) and may override `set`, `add(int, E)`, `remove(int)` and `add(E)`; the inherited `toString`, `equals`, `hashCode`, `contains`, `indexOf`, `lastIndexOf`, `isEmpty`, `iterator` (with `remove`), `forEach`, `add(E)` and `subList` call them back exactly as often and in the order the JDK's do. Passing such an object to a library method that reads it as a collection (`new ArrayList<>(range)`), and its other `List` methods (`stream`, `sort`, …), are engine limitations. `AbstractMap` and the other abstract collections are unsupported. |
|
|
135
|
+
| `Hashtable`, `Dictionary` | Supported | Every `Map` method, `contains`, and `keys()`/`elements()` enumerations, constructors `()`, `(int)` (`Illegal Capacity: -1`), `(int, float)` and `(Map)`. **Iteration order is the JDK's:** its own table (11 buckets, a key's hashCode modulo the length, new entries first in their bucket, growing to twice + 1 at three quarters full), iterated from the last bucket down; `forEach` and `replaceAll` go from the first bucket up, as the JDK's do. Enumerations read the table as it is (no `ConcurrentModificationException`); iterators fail fast. Null keys and values are the JDK's `NullPointerException`s (`Cannot invoke "Object.hashCode()" because "key" is null`). |
|
|
136
|
+
| `StringJoiner` | Supported | `add` (null is `"null"`), `merge`, `setEmptyValue`, `length`, `toString`; constructors with a delimiter, or with a prefix and suffix too, and the JDK's `The delimiter must not be null`. |
|
|
134
137
|
| `Map.Entry` | Supported | `getKey`, `getValue`, `setValue`, `equals`, `hashCode` (key's hash xor value's), `toString` (`k=v`). Named `Map.Entry`, or `Entry` after `import java.util.Map.Entry;`. |
|
|
135
|
-
| `HashSet`, `Set`, `LinkedHashSet` | Supported with limits | `add`, `contains`, `remove`, `size`, `isEmpty`, `clear`, `addAll`, `containsAll`, `equals`, `hashCode`, `iterator`, `toArray`, `toString`. Constructors `()`, `(int)`, `(Collection)`, sized as the JDK sizes them, so their order is the JDK's too. A `HashSet` is a `HashMap` of its elements, as in the JDK, and iterates in the same order; `LinkedHashSet` in insertion order. Membership is exact, and a `Set<List<Integer>>` compares lists by content. |
|
|
138
|
+
| `HashSet`, `Set`, `LinkedHashSet` | Supported with limits | `add`, `contains`, `remove`, `size`, `isEmpty`, `clear`, `addAll`, `containsAll`, `equals`, `hashCode`, `iterator`, `toArray`, `toString`. `removeAll` and `retainAll`. Constructors `()`, `(int)`, `(int, float)`, `(Collection)`, sized as the JDK sizes them, so their order is the JDK's too. A `HashSet` is a `HashMap` of its elements, as in the JDK, and iterates in the same order; `LinkedHashSet` in insertion order. Membership is exact, and a `Set<List<Integer>>` compares lists by content. `LinkedHashSet`'s `reversed()` and its `addFirst`/`getFirst` family are unsupported. |
|
|
136
139
|
| `List.of`, `Set.of`, `Map.of`, `Map.ofEntries`, `Map.entry`, `copyOf` | Supported with limits | Immutable, as the JDK's: changing one is `UnsupportedOperationException`, null elements are `NullPointerException` (with the JDK's message for each size class: `Cannot invoke "Object.hashCode()" because "pk" is null` from a `Map.of` of several entries), `get` out of range is `Index: 1 Size: 1` or `Index 5 out of bounds for length 3`, duplicates are `IllegalArgumentException: duplicate element: 1` / `duplicate key: k`. `List.of` iterates in order. The JDK randomizes the order of a `Set.of` or `Map.of` on every run, so iterating or printing one of more than one element is an engine limitation; lookups, `size` and `equals` are exact. |
|
|
137
140
|
| `Arrays.asList` | Supported | A fixed-size list over the array itself: `set` and the array see each other's changes, `add` and `remove` are `UnsupportedOperationException`, `Collections.sort` sorts the array. `Arrays.asList(intArray)` is a `List<int[]>` of one element, as in Java. |
|
|
138
|
-
| `Collections` | Supported with limits | `sort`, `reverse`, `swap`, `max`, `min` (natural order or a `Comparator`), `frequency`, `addAll`, `fill`, `shuffle` (with a seeded `Random`, the JDK's permutation), `nCopies`, `emptyList`, `emptySet`, `emptyMap`, `singletonList`, `singleton`, `singletonMap`, and the `unmodifiableList`, `Set`, `Map` and `Collection` views, with the JDK's exceptions (`List length = -1`, `Index: 1, Size: 1`, `NoSuchElementException` from `max` of an empty collection). `
|
|
141
|
+
| `Collections` | Supported with limits | `sort`, `reverse`, `swap`, `max`, `min` (natural order or a `Comparator`), `frequency`, `addAll`, `fill`, `shuffle` (with a seeded `Random`, the JDK's permutation), `nCopies`, `emptyList`, `emptySet`, `emptyMap`, `singletonList`, `singleton`, `singletonMap`, `reverseOrder` (with or without a comparator), `binarySearch` (natural order or a `Comparator`, probing the middle elements the JDK probes), `disjoint`, and the `unmodifiableList`, `Set`, `Map` and `Collection` views, with the JDK's exceptions (`List length = -1`, `Index: 1, Size: 1`, `NoSuchElementException` from `max` of an empty collection). `rotate`, `copy`, `indexOfSubList`, the synchronized and checked views and the rest are unsupported. |
|
|
139
142
|
| `toArray()`, `toArray(T[])` | Supported | On every collection: a new `Object[]`, or the given array when the elements fit (the next slot set to null), else a new array of its type; an element it cannot hold is the JDK's `ArrayStoreException: arraycopy: element type mismatch: …`. |
|
|
140
143
|
| `Comparator`, `Collections.sort` | Supported | `compare`; `reversed`, `thenComparing` (a comparator, a key, or both), `thenComparingInt`/`Long`/`Double`; `Comparator.comparing` (with or without a key comparator), `comparingInt`/`Long`/`Double`, `naturalOrder`, `reverseOrder`, `nullsFirst`, `nullsLast`; `Map.Entry.comparingByKey`/`comparingByValue`; `Collections.reverseOrder`. They compare as their documentation specifies, calling the program's lambdas and methods as Java code, with the JDK's NPE messages (`Cannot invoke "java.lang.Comparable.compareTo(Object)" because the return value of "java.util.function.Function.apply(Object)" is null`). A comparator sort is TimSort, written from its published description with Java's parameters, so even a comparator that breaks its contract (`(a, b) -> a - b` overflowing) orders elements as the JDK does, is called as many times, and fails with the same `IllegalArgumentException: Comparison method violates its general contract!` where the JDK's does. An exception in a comparator shows the lambda's frame. |
|
|
141
144
|
| Higher-order collection methods | Supported | `forEach` (every collection and map, and iterators' `forEachRemaining`), `removeIf`, `List.replaceAll`, `Map.replaceAll`, `computeIfAbsent`, `computeIfPresent`, `compute`, `merge`, `toArray(String[]::new)`, and the functions' `andThen`, `compose`, `identity`, `and`, `or`, `negate`, `Predicate.not`, `Predicate.isEqual`, `BinaryOperator.minBy`/`maxBy`. Each follows its class's JDK behavior: `HashMap.merge`, `compute` and `computeIfAbsent` add a new key at the front of its bucket (unlike `put`), so a map built with them prints in the JDK's order; a function that changes the map is a `ConcurrentModificationException`; `HashMap.forEach` finishes before reporting a change, `ArrayList.forEach` stops at it, `TreeMap.forEach` reports it at once; `ArrayList.removeIf` tests every element before removing any. Immutable collections reject them with `UnsupportedOperationException`. |
|
|
142
|
-
| Streams (`java.util.stream`) | Supported with limits | `Stream`, `IntStream`, `LongStream`, `DoubleStream`, from `collection.stream()`, `Arrays.stream` (whole or a range), `Stream.of`, `IntStream.range`/`rangeClosed`/`of`, `iterate`, `generate`, `concat`, `empty`, `String.chars()`. Intermediate: `filter`, `map`, `mapToInt`/`Long`/`Double`/`Obj`, `boxed`, `asLongStream`/`asDoubleStream`, `flatMap`, `distinct`, `sorted` (natural or a `Comparator`), `peek`, `limit`, `skip`, `takeWhile`, `dropWhile`. Terminal: `forEach`, `collect`, `toList` (unmodifiable, nulls allowed), `toArray`, `reduce`, `count`, `sum`, `min`, `max`, `average`, `summaryStatistics`, `anyMatch`/`allMatch`/`noneMatch`, `findFirst`/`findAny`. A pipeline runs as the JDK's does, which a program can observe through side effects: nothing happens before the terminal operation; each element goes through every stage before the next (`filter 1`, `filter 2`, `map 2`, …); `sorted` takes every element, then passes them on; `limit`, `findFirst` and the matches stop the source early; and `count()` of a pipeline whose size is known without running it (no `filter`, `distinct` or `flatMap`) runs nothing, so a `peek` before it prints nothing. A stream used twice is the JDK's `IllegalStateException: stream has already been operated upon or closed`. `DoubleStream.sum` and `average` use the JDK's compensated summation. Parallel streams, `iterator()`, `mapMulti`, the three-argument `collect` and `reduce`, and `LongStream`/`DoubleStream`'s `iterate`/`generate`/`concat` are unsupported. |
|
|
143
|
-
| `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
|
|
145
|
+
| Streams (`java.util.stream`) | Supported with limits | `Stream`, `IntStream`, `LongStream`, `DoubleStream`, from `collection.stream()`, `Arrays.stream` (whole or a range), `Stream.of`, `IntStream.range`/`rangeClosed`/`of`, `iterate`, `generate`, `concat`, `empty`, `String.chars()`. Intermediate: `filter`, `map`, `mapToInt`/`Long`/`Double`/`Obj`, `boxed`, `asLongStream`/`asDoubleStream`, `flatMap`, `distinct`, `sorted` (natural or a `Comparator`), `peek`, `limit`, `skip`, `takeWhile`, `dropWhile`. Terminal: `forEach`, `collect`, `toList` (unmodifiable, nulls allowed), `toArray`, `reduce`, `count`, `sum`, `min`, `max`, `average`, `summaryStatistics`, `anyMatch`/`allMatch`/`noneMatch`, `findFirst`/`findAny`. A pipeline runs as the JDK's does, which a program can observe through side effects: nothing happens before the terminal operation; each element goes through every stage before the next (`filter 1`, `filter 2`, `map 2`, …); `sorted` takes every element, then passes them on; `limit`, `findFirst` and the matches stop the source early; and `count()` of a pipeline whose size is known without running it (no `filter`, `distinct` or `flatMap`) runs nothing, so a `peek` before it prints nothing. A stream used twice is the JDK's `IllegalStateException: stream has already been operated upon or closed`. `DoubleStream.sum` and `average` use the JDK's compensated summation. **Parallel streams** (`parallel()`, `parallelStream()`, `isParallel()`, `sequential()`) run sequentially, which gives every result the JDK's parallel run gives (sums, counts, `collect`, `reduce` with an associative operator, `sorted`, `forEachOrdered`, `findFirst`, `limit`); what the JDK's threads decide (the order of `forEach` and `peek`, which element `findAny` returns) is an engine limitation on a parallel stream, and `unordered()` is unsupported. A lambda's side effects run in encounter order, one legal order of the JDK's. `iterator()`, `mapMulti`, the three-argument `collect` and `reduce`, and `LongStream`/`DoubleStream`'s `iterate`/`generate`/`concat` are unsupported. |
|
|
146
|
+
| `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)`. |
|
|
144
147
|
| `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
|
+
| `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` dates** (ADR 0025) | 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, ChronoUnit)`, `plus(Period)`, `with…`, `isBefore`/`isAfter`/`isEqual`, `until`, `datesUntil`, `format`, `toString` with the JDK's year signs, `hashCode`, Comparable), `Period` (`between` with the JDK's borrow, `of…`, the getters, `normalized`, `multipliedBy`, `P1Y2M3D`), `DayOfWeek` and `Month` (`of`, `getValue`, `plus`, `minus`, `length`), `ChronoUnit` (`between` for the date units; a time unit is the JDK's `UnsupportedTemporalTypeException: Unsupported unit: Hours`), and `DateTimeFormatter` (`ofPattern` with the date letters `y u M L d D E` and quoted text, `ISO_LOCAL_DATE`). Parsing resolves as the JDK's: an `ofPattern` formatter clamps `31/04` to April 30, `ISO_LOCAL_DATE` rejects `2024-02-30`; the JDK's `DateTimeException` and `DateTimeParseException` messages, with the cause. A switch on `DayOfWeek`, `Month`, `ChronoUnit` or `RoundingMode` takes their constants as labels. Times (`LocalTime`, `LocalDateTime`, `Instant`, `Duration`), time zones, other pattern letters, `getDisplayName` and printing a formatter are unsupported or engine limitations. |
|
|
145
150
|
| `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). |
|
|
146
151
|
| `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. |
|
|
147
152
|
| `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. |
|
|
148
|
-
| `Iterator`, `Iterable`, `Collection` | Supported | `hasNext`, `next`, `remove`, with the JDK's `NoSuchElementException`, `IllegalStateException` and `ConcurrentModificationException`. |
|
|
149
|
-
| `StringBuilder` | Supported | `append` (every supported type, `char[]`, and objects through their `toString()`), `insert`, `delete`, `deleteCharAt`, `replace`, `reverse` (surrogate pairs stay in order), `charAt`, `setCharAt`, `setLength`, `length`, `isEmpty`, `indexOf`, `lastIndexOf`, `substring`, `compareTo`, `equals` and `hashCode` (identity), `toString
|
|
153
|
+
| `Iterator`, `ListIterator`, `Iterable`, `Collection` | Supported | `hasNext`, `next`, `remove`, with the JDK's `NoSuchElementException`, `IllegalStateException` and `ConcurrentModificationException`; a `ListIterator` adds `hasPrevious`, `previous`, `nextIndex`, `previousIndex`, `set` and `add`. `Collection`'s `removeAll` and `retainAll` on every collection (`UnsupportedOperationException` on the immutable and unmodifiable ones). `parallelStream()` is a parallel stream (*Streams*). `spliterator` is unsupported. |
|
|
154
|
+
| `StringBuilder`, `StringBuffer` | Supported | `append` (every supported type, `char[]`, and objects through their `toString()`), `insert`, `delete`, `deleteCharAt`, `replace`, `reverse` (surrogate pairs stay in order), `charAt`, `setCharAt`, `setLength`, `length`, `isEmpty`, `indexOf`, `lastIndexOf`, `substring`, `compareTo`, `equals` and `hashCode` (identity), `toString`, and `capacity`, `ensureCapacity`, `trimToSize` with the JDK's sizes (16, `n`, or a String's length + 16; growing to twice + 2, or what is needed; `append(double)` makes room for 24 chars first, `append(float)` for 15). Constructors `()`, `(int)`, `(String)`. `StringBuffer` has the same methods and its own class. Index errors with the JDK's messages: `Index 10 out of bounds for length 3`, `Range [4, 3) out of bounds for length 3`, `String index out of range: -1`. |
|
|
150
155
|
| `Number`, `Integer`, `Long`, `Double`, `Float`, `Byte`, `Short`, `Boolean` methods | Supported with limits | `Number` is the numeric wrappers' superclass, with `byteValue`, `shortValue`, `intValue`, `longValue`, `floatValue` and `doubleValue` (`List<Number>`, `T extends Number`, `List<? extends Number>`; `new Number()` is javac's `Number is abstract; cannot be instantiated`). Statics: `parseInt` and `parseLong` (with a radix), `parseDouble`, `parseBoolean`, `valueOf`, `toString`, `compare`, `max`, `min`, `sum`, `signum`, `bitCount`, `toBinaryString`, `toHexString`, `toOctalString`, `numberOfLeadingZeros`, `numberOfTrailingZeros`, `highestOneBit`, `reverse`, `hashCode`, `isNaN`, `isInfinite`, `isFinite`, `logicalAnd`, `logicalOr`, `logicalXor`. On boxed values: `intValue`, `longValue`, `doubleValue`, `charValue`, `booleanValue`, `isNaN`, `isInfinite`, `compareTo`, `equals`, `hashCode`, `toString`. The JDK's `NumberFormatException` messages: `For input string: "12a"`, `… under radix 16`, `Cannot parse null string`, `empty String`. `Float`: `parseFloat` (rounded once, never through double), `floatToIntBits`, `floatToRawIntBits`, `intBitsToFloat`, and Double's other statics; `Float.valueOf` never caches, as on the JDK. `Byte` and `Short`: `parseByte`/`parseShort` (with a radix; `Value out of range. Value:"128" Radix:10`), `toUnsignedInt`, `toUnsignedLong`, and the caches (every `Byte`, `Short` in -128..127). `parseDouble` and `parseFloat` read hexadecimal strings, and report `multiple points` as the JDK does. |
|
|
151
|
-
| `Character` methods | Supported with limits | `isLetter`, `isDigit`, `isLetterOrDigit`, `isAlphabetic`, `isUpperCase`, `isLowerCase`, `isWhitespace`, `isSpaceChar`, `toUpperCase`, `toLowerCase` (the `char` and `int` forms), `getNumericValue`, `digit`, `forDigit`, `valueOf`, `toString`, `compare`, `hashCode
|
|
152
|
-
| `Arrays` | Supported with limits | `toString`, `deepToString`, `sort` (whole or a range, for every primitive array but `boolean[]`, and object arrays; objects in natural order or by a `Comparator`, stably), `fill` (whole or a range), `equals`, `hashCode`, `binarySearch`, and `copyOf` and `copyOfRange` (an object array's copy keeps its class: a `String[]` stays a `String[]`). The JDK's exceptions: `fromIndex(2) > toIndex(1)`, `Array index out of range: 4`, `ArrayStoreException: java.lang.Integer`, and `Cannot read the array length because "a" is null`. `asList` is below. `stream` is below. Sorting a primitive array with a comparator is javac's `no suitable method` error. Sorting an object array that contains null is an engine limitation. |
|
|
156
|
+
| `Character` methods | Supported with limits | `isLetter`, `isDigit`, `isLetterOrDigit`, `isAlphabetic`, `isUpperCase`, `isLowerCase`, `isWhitespace`, `isSpaceChar`, `toUpperCase`, `toLowerCase` (the `char` and `int` forms), `getNumericValue`, `digit`, `forDigit`, `valueOf`, `toString`, `compare`, `hashCode`, `toChars` (`Not a valid Unicode code point: 0x110000`). Exact for Latin-1 (U+0000 to U+00FF), whose answers were recorded from JDK 25: `é` is a letter, `ÿ` upper-cases to `Ÿ`, and `ß` stays `ß`. Other characters are an engine limitation (SPEC.md §4.2.2). |
|
|
157
|
+
| `Arrays` | Supported with limits | `toString`, `deepToString`, `sort` (whole or a range, for every primitive array but `boolean[]`, and object arrays; objects in natural order or by a `Comparator`, stably), `fill` (whole or a range), `equals`, `hashCode`, `deepEquals`, `deepHashCode`, `binarySearch`, and `copyOf` and `copyOfRange` (an object array's copy keeps its class: a `String[]` stays a `String[]`). The JDK's exceptions: `fromIndex(2) > toIndex(1)`, `Array index out of range: 4`, `ArrayStoreException: java.lang.Integer`, and `Cannot read the array length because "a" is null`. `asList` is below. `stream` is below. Sorting a primitive array with a comparator is javac's `no suitable method` error. Sorting an object array that contains null is an engine limitation. |
|
|
153
158
|
| Other `PrintStream` methods, `System.in`'s own methods, the `System`, `Math` and `String` methods not listed here, array methods; other java.util classes; the library methods not listed here | Unsupported | A real method of a supported class is reported as `the List method parallelStream() is not supported in this version`, not as `cannot find symbol`. An overload outside the subset is chosen as javac would choose it, then reported (`the constructor HashSet(int, float) is not supported`). |
|
|
154
159
|
|
|
155
160
|
## Practice mode
|
|
@@ -234,6 +239,7 @@ These all use javac's wording and caret positions, as evidenced by `tests/jdk-ca
|
|
|
234
239
|
| A regex that backtracks exponentially (`(a+)+b` on a long run of `a`) | Runs for a very long time | Also runs for a very long time; JavaScript's regex engine is not interrupted by the instruction limit | Stopping terminates the worker (SPEC.md §6.1) |
|
|
235
240
|
| A `ClassCastException` about the program's classes | Names the source launcher's class loader with its identity hash (`MemoryClassLoader @78186a70`), different on every run | The same message with a fixed hash | Recorded cases mask the hash (`loader-hash`) |
|
|
236
241
|
| `Scanner.nextDouble()` of `3.5` | Depends on the JDK's default locale: `3.5` under English (the reference JDK's), not a number under German, where the decimal separator is `,` | The English locale's rules, always: `.` is the decimal separator and `,` groups thousands (owner decision, 2026-10-18: online judges and the reference JDK run under English, and the result does not depend on the machine) | Recorded under the reference JDK's locale (`sc-*`) |
|
|
242
|
+
| `System.out.println(stream.collect(Collectors.groupingBy(f, TreeMap::new, Collectors.counting())))`, where only `println(String)` applies to the generic result | javac's `cannot be applied` error lists every inference bound and type variable of the nested calls (`T#1`, `T#2`, …) | The same header, caret, required and found types and first reason line | `first-diagnostic` |
|
|
237
243
|
| Requesting an array of about 2³¹ elements | `OutOfMemoryError: Requested array size exceeds VM limit` | `resource-limit` (array budget) | Engine-only test |
|
|
238
244
|
|
|
239
245
|
## Engine limitations (reported as `engine-limitation`)
|
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.
|
|
12
|
+
<script type="module" src="https://cdn.jsdelivr.net/npm/code-playpad@0.6.0/dist/standalone.js"></script>
|
|
13
13
|
|
|
14
14
|
<code-playpad height="auto">
|
|
15
15
|
print("hello from a static page")
|
|
@@ -29,7 +29,7 @@ entirely in the reader's browser. No backend, no iframe, no sign-up.
|
|
|
29
29
|
| --- | --- | --- |
|
|
30
30
|
| `python` (default) | Python 3.14 via Pyodide — full standard library, `input()`, real tracebacks, `numpy` on demand | ~6 MB (13.5 MB unpacked), once, cached |
|
|
31
31
|
| `javascript` | The browser's own engine, in a Worker | nothing |
|
|
32
|
-
| `typescript` | Same engine, types stripped before running | ~
|
|
32
|
+
| `typescript` | Same engine, types stripped before running | nothing from another service: a ~47 KB (gzipped) transform chunk of this package, loaded the first time a widget needs it |
|
|
33
33
|
| `java` | A documented subset of Java 25, compiled and interpreted in a Worker by an engine built for this package — see [Java](#java) | nothing: the engine is a ~105 KB (gzipped) chunk of this package, loaded with the first Java widget, and its library a ~75 KB chunk loaded the first time a program uses it |
|
|
34
34
|
|
|
35
35
|
```html
|
|
@@ -170,20 +170,24 @@ actually sent.
|
|
|
170
170
|
| --- | --- | --- | --- |
|
|
171
171
|
| 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
172
|
| JavaScript | **180.4 KB** | nothing | 179.9 KB |
|
|
173
|
-
| TypeScript | **
|
|
174
|
-
| Java | **
|
|
175
|
-
| Java, with collections | **
|
|
176
|
-
| All four |
|
|
173
|
+
| 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 | **277.4 KB** (0.6.0: engine 0.31) | nothing | 216.4 KB |
|
|
175
|
+
| Java, with collections | **372.5 KB** (0.6.0) | nothing | 233.2 KB |
|
|
176
|
+
| All four | 476.9 KB (0.6.0) | Pyodide | 273.9 KB |
|
|
177
177
|
|
|
178
178
|
- **Every row includes a 144.5 KB shared base:** the editor (CodeMirror) and
|
|
179
179
|
the widget, the same as in 0.3.0.
|
|
180
180
|
- **Each language adds:**
|
|
181
181
|
- Python: 21.7 KB.
|
|
182
182
|
- JavaScript/TypeScript: 35.9 KB.
|
|
183
|
-
- Java:
|
|
183
|
+
- Java: 132.8 KB (the 113.8 KB engine plus 19 KB of Java syntax
|
|
184
184
|
highlighting).
|
|
185
185
|
- The first Java program that uses collections, `StringBuilder` or another
|
|
186
|
-
library class also adds the
|
|
186
|
+
library class also adds the 95.1 KB Java library, once per page.
|
|
187
|
+
- The Java figures for 0.6.0 are the 0.4.0 measurements plus what the
|
|
188
|
+
engine's two chunks grew by in the build's gzip sizes (engines 0.28 to
|
|
189
|
+
0.31 added the collection staples, library subclasses, the tutorial APIs,
|
|
190
|
+
regex, java.time dates and more).
|
|
187
191
|
- **Java grew** from 0.3.0 because the subset did, from basic Java to most of
|
|
188
192
|
what practice programs use (see the version history). The owner treats
|
|
189
193
|
download size as secondary to coverage. The package's size checks still
|
|
@@ -192,8 +196,12 @@ actually sent.
|
|
|
192
196
|
- **Languages load lazily.** A Java page never fetches the Python or
|
|
193
197
|
JavaScript runtimes, and Python and JavaScript pages never fetch Java. As a
|
|
194
198
|
result, Python-only and JavaScript-only pages are the same size as in 0.3.0.
|
|
195
|
-
- **Java
|
|
196
|
-
|
|
199
|
+
- **Java and TypeScript need no other service:** both are self-contained.
|
|
200
|
+
Since 0.5.2 the TypeScript transform (Sucrase) is a 46.9 KB chunk of this
|
|
201
|
+
package, loaded the first time a widget needs it (TypeScript, JSX, or
|
|
202
|
+
JavaScript modules across several files); the TypeScript rows are the
|
|
203
|
+
measured JavaScript page plus that chunk. Python's first run downloads about
|
|
204
|
+
6 MB of Pyodide (cached after that).
|
|
197
205
|
- **With npm and a bundler,** you already ship CodeMirror yourself.
|
|
198
206
|
code-playpad's own code then costs about 9 KB, plus the runtime chunk for
|
|
199
207
|
each language used. Java's chunk is 104 KB, and 74 KB more for its library
|
|
@@ -204,7 +212,7 @@ actually sent.
|
|
|
204
212
|
### From a CDN — nothing to install
|
|
205
213
|
|
|
206
214
|
```html
|
|
207
|
-
<script type="module" src="https://cdn.jsdelivr.net/npm/code-playpad@0.
|
|
215
|
+
<script type="module" src="https://cdn.jsdelivr.net/npm/code-playpad@0.6.0/dist/standalone.js"></script>
|
|
208
216
|
```
|
|
209
217
|
|
|
210
218
|
This is the `standalone` build: CodeMirror is bundled in, so a static blog post
|
|
@@ -806,8 +814,11 @@ configurePython({ indexURL: '/pyodide/' }); // before the first run
|
|
|
806
814
|
pyodideAssetUrls(); // the files worth <link rel=preload>-ing
|
|
807
815
|
```
|
|
808
816
|
|
|
809
|
-
|
|
810
|
-
|
|
817
|
+
The TypeScript transform needs no configuration: it ships in the package (since
|
|
818
|
+
0.5.2) and loads from wherever the package is served. `configureTypeScript({
|
|
819
|
+
sucraseURL })` loads it from a URL of your own instead (an absolute URL of a
|
|
820
|
+
self-contained ES module exporting `transform`), set before the first
|
|
821
|
+
JavaScript or TypeScript widget starts its runtime. Give those files a long `Cache-Control`: one page's download then
|
|
811
822
|
warms every other page on the site.
|
|
812
823
|
|
|
813
824
|
## Worth knowing
|
|
@@ -832,9 +843,75 @@ warms every other page on the site.
|
|
|
832
843
|
|
|
833
844
|
## Version history
|
|
834
845
|
|
|
835
|
-
Markup and API written against 0.1.3 still work on 0.
|
|
846
|
+
Markup and API written against 0.1.3 still work on 0.6.0, with one exception, in
|
|
836
847
|
0.5.1: an `entry` that names none of a widget's files is now an error.
|
|
837
848
|
|
|
849
|
+
### 0.6.0
|
|
850
|
+
|
|
851
|
+
Java engine 0.27.1 → 0.31.0: the rest of what practice programs commonly use,
|
|
852
|
+
each checked against JDK 25. Nothing else changed: Python, JavaScript and
|
|
853
|
+
TypeScript, the element's API and its markup are as in 0.5.2.
|
|
854
|
+
|
|
855
|
+
- **Java engine 0.28.0.** Collection methods that practice programs use
|
|
856
|
+
every day now work: `removeAll` and `retainAll`, `listIterator()`,
|
|
857
|
+
`reversed()` (a live view, as on the JDK), and `LinkedHashMap` in access
|
|
858
|
+
order (`new LinkedHashMap<>(16, 0.75f, true)`, the classic LRU cache). Also
|
|
859
|
+
new: `(var a, var b) -> a + b` lambdas, `array.clone()`,
|
|
860
|
+
`Collections.binarySearch` and `disjoint`, `Collectors.teeing`,
|
|
861
|
+
`Math.ceilDiv`, `String.codePointAt`, `getBytes()` and `transform`,
|
|
862
|
+
`Character.toChars`, and `Boolean.TRUE`.
|
|
863
|
+
- **Java: clearer messages.** A fully qualified name such as
|
|
864
|
+
`java.util.stream.IntStream.range(0, 3)` now works without an import, and
|
|
865
|
+
one naming a JDK class outside the subset (`java.time.LocalDate.of(...)`)
|
|
866
|
+
says "not supported in this version" instead of `cannot find symbol`.
|
|
867
|
+
- **JAVA-COMPATIBILITY.md is accurate again.** Ten methods it listed as
|
|
868
|
+
unsupported had already shipped. A test now checks the table against the
|
|
869
|
+
engine, so it cannot drift again.
|
|
870
|
+
- **Java engine 0.29.0: classes can extend the library's collections.**
|
|
871
|
+
`class LRUCache<K, V> extends LinkedHashMap<K, V>` with `removeEldestEntry`,
|
|
872
|
+
a `History extends ArrayList<String>` that overrides `add`, a word counter
|
|
873
|
+
over `HashMap`, `new ArrayList<>() {{ add("a"); }}`: these now run as on
|
|
874
|
+
the JDK. Overriding is limited to methods where this cannot change the
|
|
875
|
+
result. Where it could, the engine says so instead of running differently.
|
|
876
|
+
- **Java engine 0.30.0: the APIs older tutorials teach.** `Vector`,
|
|
877
|
+
`Hashtable` (printing in the JDK's own order), `Enumeration`,
|
|
878
|
+
`StringBuffer`, `new Integer(5)` (with javac's deprecation warnings),
|
|
879
|
+
`StringJoiner`, `String.CASE_INSENSITIVE_ORDER`, and `outer.new Inner()`.
|
|
880
|
+
Also `java.util.regex`: `Pattern.compile`, `Matcher.find`, `group`
|
|
881
|
+
(by number or name), `replaceAll`, `appendReplacement`, `results()`.
|
|
882
|
+
- **Java engine 0.31.0: dates and more.** `LocalDate`, `Period`,
|
|
883
|
+
`DayOfWeek`, `Month`, `ChronoUnit.DAYS.between` and `DateTimeFormatter`
|
|
884
|
+
date patterns, `switch` on a `DayOfWeek`; `BitSet`; parallel streams
|
|
885
|
+
(results as the JDK's; what its threads decide is reported); and classes
|
|
886
|
+
extending `AbstractList`. Also javac's `reference to println is ambiguous`
|
|
887
|
+
for `println(stream.collect(collectingAndThen(..., l -> ...)))`, which the
|
|
888
|
+
engine used to run though javac rejects it.
|
|
889
|
+
- **Java: stack traces through generic interfaces match the JDK.** An
|
|
890
|
+
exception thrown inside `compareTo`, `compare`, an `Iterator`'s `next` or
|
|
891
|
+
a `Function`'s `apply` now shows the second frame the JDK shows (javac's
|
|
892
|
+
bridge method), and a raw call with a wrong argument type fails with the
|
|
893
|
+
JDK's `ClassCastException` instead of running.
|
|
894
|
+
|
|
895
|
+
### 0.5.2
|
|
896
|
+
|
|
897
|
+
- **TypeScript no longer depends on esm.sh.** Before, the first TypeScript
|
|
898
|
+
run (and JSX, and JavaScript modules across several files) imported Sucrase,
|
|
899
|
+
the transform that strips types, from `esm.sh`. If esm.sh was blocked or
|
|
900
|
+
failed, TypeScript could not run (`Failed to fetch dynamically imported
|
|
901
|
+
module`). Sucrase 3.35.1 now ships in the package as its own chunk (46.9 KB
|
|
902
|
+
gzipped, about a third smaller than what esm.sh sent). It loads from wherever
|
|
903
|
+
code-playpad is served: the same CDN, or your app's bundle. It is still
|
|
904
|
+
loaded only when a widget first needs it, so JavaScript-only, Python and
|
|
905
|
+
Java pages never download it.
|
|
906
|
+
- **A failed transform load can be retried, and says what it is.** Before, one
|
|
907
|
+
failed load kept every later run failing until the page was reloaded, and
|
|
908
|
+
the error looked like one in the learner's code. Now the message is *Could
|
|
909
|
+
not load the TypeScript transform (Sucrase)*, with a hint that it is not an
|
|
910
|
+
error in the code, and the next Run tries again.
|
|
911
|
+
- **Types are still erased, not checked.** This changes where the transform
|
|
912
|
+
comes from, not what it does.
|
|
913
|
+
- `configureTypeScript({ sucraseURL })` still works, and is now optional.
|
|
914
|
+
|
|
838
915
|
### 0.5.1
|
|
839
916
|
|
|
840
917
|
- **A wrong `entry` is an error, in every language.** Before, a widget whose
|