wasm gc: fix Date API support

This commit is contained in:
Alexey Andreev 2024-09-26 18:24:15 +02:00
parent b9f406dcaa
commit 951d0c53c3
6 changed files with 98 additions and 15 deletions

View File

@ -64,6 +64,8 @@ public class TDate implements TComparable<TDate> {
public TDate(int year, int month, int date, int hrs, int min, int sec) { public TDate(int year, int month, int date, int hrs, int min, int sec) {
this(PlatformDetector.isLowLevel() this(PlatformDetector.isLowLevel()
? initDateLowLevel(year, month, date, hrs, min, sec) ? initDateLowLevel(year, month, date, hrs, min, sec)
: PlatformDetector.isWebAssemblyGC()
? (long) initDateWasmGC(year + 1900, month, date, hrs, min, sec)
: (long) new JSDate(year, month, date, hrs, min, sec).getTime()); : (long) new JSDate(year, month, date, hrs, min, sec).getTime());
if (!PlatformDetector.isLowLevel()) { if (!PlatformDetector.isLowLevel()) {
setYear(year); setYear(year);
@ -77,6 +79,10 @@ public class TDate implements TComparable<TDate> {
@UnsupportedOn(Platforms.WEBASSEMBLY) @UnsupportedOn(Platforms.WEBASSEMBLY)
private static native long initDateLowLevel(int year, int month, int date, int hrs, int min, int sec); private static native long initDateLowLevel(int year, int month, int date, int hrs, int min, int sec);
@Import(name = "create", module = "teavmDate")
@NoSideEffects
private static native double initDateWasmGC(int year, int month, int date, int hrs, int min, int sec);
public TDate(String s) { public TDate(String s) {
this(parse(s)); this(parse(s));
} }
@ -90,6 +96,8 @@ public class TDate implements TComparable<TDate> {
public static long UTC(int year, int month, int date, int hrs, int min, int sec) { public static long UTC(int year, int month, int date, int hrs, int min, int sec) {
if (PlatformDetector.isLowLevel()) { if (PlatformDetector.isLowLevel()) {
return initUtcDateLowLevel(year, month, date, hrs, min, sec); return initUtcDateLowLevel(year, month, date, hrs, min, sec);
} else if (PlatformDetector.isWebAssemblyGC()) {
return (long) initUtcDateWasmGC(year + 1900, month, date, hrs, min, sec);
} else { } else {
return (long) JSDate.UTC(year + 1900, month, date, hrs, min, sec); return (long) JSDate.UTC(year + 1900, month, date, hrs, min, sec);
} }
@ -102,6 +110,9 @@ public class TDate implements TComparable<TDate> {
@UnsupportedOn(Platforms.WEBASSEMBLY) @UnsupportedOn(Platforms.WEBASSEMBLY)
private static native long initUtcDateLowLevel(int year, int month, int date, int hrs, int min, int sec); private static native long initUtcDateLowLevel(int year, int month, int date, int hrs, int min, int sec);
@Import(name = "createFromUTC", module = "teavmDate")
private static native double initUtcDateWasmGC(int year, int month, int date, int hrs, int min, int sec);
@Deprecated @Deprecated
public static long parse(String s) { public static long parse(String s) {
if (PlatformDetector.isLowLevel()) { if (PlatformDetector.isLowLevel()) {
@ -126,10 +137,15 @@ public class TDate implements TComparable<TDate> {
public int getYear() { public int getYear() {
if (PlatformDetector.isLowLevel()) { if (PlatformDetector.isLowLevel()) {
return getYearLowLevel(value); return getYearLowLevel(value);
} else if (PlatformDetector.isWebAssemblyGC()) {
return getYearWasmGC(value) - 1900;
} }
return new JSDate(value).getFullYear() - 1900; return new JSDate(value).getFullYear() - 1900;
} }
@Import(name = "getYear", module = "teavmDate")
private static native int getYearWasmGC(double timestamp);
@Import(name = "teavm_date_getYear") @Import(name = "teavm_date_getYear")
@NoSideEffects @NoSideEffects
@Unmanaged @Unmanaged
@ -142,12 +158,18 @@ public class TDate implements TComparable<TDate> {
if (PlatformDetector.isLowLevel()) { if (PlatformDetector.isLowLevel()) {
value = setYearLowLevel(value, year); value = setYearLowLevel(value, year);
return; return;
} else if (PlatformDetector.isWebAssemblyGC()) {
value = (long) setYearWasmGC(value, year + 1900);
return;
} }
var date = new JSDate(value); var date = new JSDate(value);
date.setFullYear(year + 1900); date.setFullYear(year + 1900);
value = (long) date.getTime(); value = (long) date.getTime();
} }
@Import(name = "setYear", module = "teavmDate")
private static native double setYearWasmGC(double timestamp, int year);
@Import(name = "teavm_date_setYear") @Import(name = "teavm_date_setYear")
@NoSideEffects @NoSideEffects
@Unmanaged @Unmanaged
@ -159,6 +181,8 @@ public class TDate implements TComparable<TDate> {
public int getMonth() { public int getMonth() {
if (PlatformDetector.isLowLevel()) { if (PlatformDetector.isLowLevel()) {
return getMonthLowLevel(value); return getMonthLowLevel(value);
} else if (PlatformDetector.isWebAssemblyGC()) {
return getMonthWasmGC(value);
} }
return new JSDate(value).getMonth(); return new JSDate(value).getMonth();
} }
@ -170,11 +194,17 @@ public class TDate implements TComparable<TDate> {
@UnsupportedOn(Platforms.WEBASSEMBLY) @UnsupportedOn(Platforms.WEBASSEMBLY)
private static native int getMonthLowLevel(long date); private static native int getMonthLowLevel(long date);
@Import(name = "getMonth", module = "teavmDate")
private static native int getMonthWasmGC(double timestamp);
@Deprecated @Deprecated
public void setMonth(int month) { public void setMonth(int month) {
if (PlatformDetector.isLowLevel()) { if (PlatformDetector.isLowLevel()) {
value = setMonthLowLevel(value, month); value = setMonthLowLevel(value, month);
return; return;
} else if (PlatformDetector.isWebAssemblyGC()) {
value = (long) setMonthWasmGC(value, month);
return;
} }
var date = new JSDate(value); var date = new JSDate(value);
date.setMonth(month); date.setMonth(month);
@ -188,10 +218,15 @@ public class TDate implements TComparable<TDate> {
@UnsupportedOn(Platforms.WEBASSEMBLY) @UnsupportedOn(Platforms.WEBASSEMBLY)
private static native long setMonthLowLevel(long date, int month); private static native long setMonthLowLevel(long date, int month);
@Import(name = "setMonth", module = "teavmDate")
private static native double setMonthWasmGC(double timestamp, int month);
@Deprecated @Deprecated
public int getDate() { public int getDate() {
if (PlatformDetector.isLowLevel()) { if (PlatformDetector.isLowLevel()) {
return getDateLowLevel(value); return getDateLowLevel(value);
} else if (PlatformDetector.isWebAssemblyGC()) {
return getDateWasmGC(value);
} }
return new JSDate(value).getDate(); return new JSDate(value).getDate();
} }
@ -203,11 +238,17 @@ public class TDate implements TComparable<TDate> {
@UnsupportedOn(Platforms.WEBASSEMBLY) @UnsupportedOn(Platforms.WEBASSEMBLY)
private static native int getDateLowLevel(long date); private static native int getDateLowLevel(long date);
@Import(name = "getDate", module = "teavmDate")
private static native int getDateWasmGC(double timestamp);
@Deprecated @Deprecated
public void setDate(int date) { public void setDate(int date) {
if (PlatformDetector.isLowLevel()) { if (PlatformDetector.isLowLevel()) {
value = setDateLowLevel(value, date); value = setDateLowLevel(value, date);
return; return;
} else if (PlatformDetector.isWebAssemblyGC()) {
value = (long) setDateWasmGC(value, date);
return;
} }
var d = new JSDate(value); var d = new JSDate(value);
d.setDate(date); d.setDate(date);
@ -221,6 +262,9 @@ public class TDate implements TComparable<TDate> {
@UnsupportedOn(Platforms.WEBASSEMBLY) @UnsupportedOn(Platforms.WEBASSEMBLY)
private static native int setDateLowLevel(long target, int date); private static native int setDateLowLevel(long target, int date);
@Import(name = "setDate", module = "teavmDate")
private static native double setDateWasmGC(double timestamp, int date);
@Deprecated @Deprecated
public int getDay() { public int getDay() {
if (PlatformDetector.isLowLevel()) { if (PlatformDetector.isLowLevel()) {
@ -373,8 +417,10 @@ public class TDate implements TComparable<TDate> {
public String toString() { public String toString() {
if (PlatformDetector.isC()) { if (PlatformDetector.isC()) {
return toStringC(value); return toStringC(value);
} else if (PlatformDetector.isWebAssembly() || PlatformDetector.isWebAssemblyGC()) { } else if (PlatformDetector.isWebAssembly()) {
return toStringWebAssembly(value); return toStringWebAssembly(value);
} else if (PlatformDetector.isWebAssemblyGC()) {
return toStringWebAssemblyGC(value);
} else { } else {
return JSDate.create(value).stringValue(); return JSDate.create(value).stringValue();
} }
@ -388,6 +434,9 @@ public class TDate implements TComparable<TDate> {
@Import(module = "teavm", name = "dateToString") @Import(module = "teavm", name = "dateToString")
private static native String toStringWebAssembly(double date); private static native String toStringWebAssembly(double date);
@Import(module = "teavmDate", name = "dateToString")
private static native String toStringWebAssemblyGC(double date);
@Deprecated @Deprecated
public String toLocaleString() { public String toLocaleString() {
return new JSDate(value).toLocaleFormat("%c"); return new JSDate(value).toLocaleFormat("%c");

View File

@ -32,7 +32,7 @@ public class SystemIntrinsic implements WasmGCIntrinsic {
workerFunction = new WasmFunction(context.functionTypes().of(WasmType.FLOAT64)); workerFunction = new WasmFunction(context.functionTypes().of(WasmType.FLOAT64));
workerFunction.setName("teavm@currentTimeMillis"); workerFunction.setName("teavm@currentTimeMillis");
workerFunction.setImportName("currentTimeMillis"); workerFunction.setImportName("currentTimeMillis");
workerFunction.setImportModule("teavm"); workerFunction.setImportModule("teavmDate");
context.module().functions.add(workerFunction); context.module().functions.add(workerFunction);
} }
var call = new WasmCall(workerFunction); var call = new WasmCall(workerFunction);

View File

@ -48,10 +48,10 @@ public class WasmGCSupport {
return x; return x;
} }
@Import(name = "putcharStdout") @Import(name = "putcharStdout", module = "teavmConsole")
public static native void putCharStdout(char c); public static native void putCharStdout(char c);
@Import(name = "putcharStderr") @Import(name = "putcharStderr", module = "teavmConsole")
public static native void putCharStderr(char c); public static native void putCharStderr(char c);
public static char[] nextCharArray() { public static char[] nextCharArray() {

View File

@ -28,7 +28,45 @@ TeaVM.wasm = function() {
let stringFinalizationRegistry = new FinalizationRegistry(heldValue => { let stringFinalizationRegistry = new FinalizationRegistry(heldValue => {
exports.reportGarbageCollectedString(heldValue); exports.reportGarbageCollectedString(heldValue);
}); });
imports.teavm = { imports.teavmDate = {
currentTimeMillis() {
return new Date().getTime();
},
dateToString(timestamp) {
return stringToJava(new Date(timestamp).toString());
},
getYear(timestamp) {
return new Date(timestamp).getFullYear();
},
setYear(timestamp, year) {
let date = new Date(timestamp);
date.setFullYear(year);
return date.getTime();
},
getMonth(timestamp) {
return new Date(timestamp).getMonth();
},
setMonth(timestamp, month) {
let date = new Date(timestamp);
date.setMonth(month);
return date.getTime();
},
getDate(timestamp) {
return new Date(timestamp).getDate();
},
setDate(timestamp, value) {
let date = new Date(timestamp);
date.setDate(value);
return date.getTime();
},
create(year, month, date, hrs, min, sec) {
return new Date(year, month, date, hrs, min, sec).getTime();
},
createFromUTC(year, month, date, hrs, min, sec) {
return Date.UTC(year, month, date, hrs, min, sec);
}
};
imports.teavmConsole = {
putcharStderr(c) { putcharStderr(c) {
if (c === 10) { if (c === 10) {
console.error(stderr); console.error(stderr);
@ -45,12 +83,8 @@ TeaVM.wasm = function() {
stdout += String.fromCharCode(c); stdout += String.fromCharCode(c);
} }
}, },
currentTimeMillis() { };
return new Date().getTime(); imports.teavm = {
},
dateToString(timestamp) {
return stringToJava(new Date(timestamp).toString());
},
createWeakRef(value, heldValue) { createWeakRef(value, heldValue) {
let weakRef = new WeakRef(value); let weakRef = new WeakRef(value);
if (heldValue !== null) { if (heldValue !== null) {

View File

@ -35,8 +35,8 @@
function putwchar(ch) { function putwchar(ch) {
$rt_putStdoutCustom(String.fromCharCode(ch)); $rt_putStdoutCustom(String.fromCharCode(ch));
} }
o.teavm.putcharStderr = putwchar; o.teavmConsole.putcharStderr = putwchar;
o.teavm.putcharStdout = putwchar; o.teavmConsole.putcharStdout = putwchar;
}, },
}).then(teavm => { }).then(teavm => {
this.instance = teavm.instance; this.instance = teavm.instance;

View File

@ -212,8 +212,8 @@ function launchWasmGCTest(file, argument, callback) {
TeaVM.wasm.load(file.path, { TeaVM.wasm.load(file.path, {
installImports: function(o) { installImports: function(o) {
o.teavm.putcharStdout = putchar; o.teavmConsole.putcharStdout = putchar;
o.teavm.putcharStderr = putcharStderr; o.teavmConsole.putcharStderr = putcharStderr;
o.teavmTest = { o.teavmTest = {
success() { success() {
callback(wrapResponse({ status: "OK" })); callback(wrapResponse({ status: "OK" }));