Create environments #4
7
Metadata.java
Normal file
7
Metadata.java
Normal file
@ -0,0 +1,7 @@
|
||||
package me.topchetoeu.jscript;
|
||||
|
||||
public class Metadata {
|
||||
public static final String VERSION = "0.0.1-alpha";
|
||||
public static final String AUTHOR = "TopchetoEU";
|
||||
public static final String NAME = "java-jscript";
|
||||
}
|
2
build.js
2
build.js
@ -46,7 +46,7 @@ async function compileJava() {
|
||||
|
||||
const args = ['-d', 'dst/classes', 'Metadata.java'];
|
||||
for await (const path of find('src', undefined, v => v.endsWith('.java') && !v.endsWith('Metadata.java'))) args.push(path);
|
||||
await run('javac', ...args);
|
||||
await run(conf.javahome + '/javac', ...args);
|
||||
await fs.rm('Metadata.java');
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
/** @internal */
|
||||
define("values/object", () => {
|
||||
var Object = env.global.Object = function(arg: any) {
|
||||
if (arg === undefined || arg === null) return {};
|
||||
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"version": "0.0.1-alpha",
|
||||
"name": "java-jscript",
|
||||
"author": "TopchetoEU"
|
||||
"author": "TopchetoEU",
|
||||
"javahome": "/usr/lib/jvm/java-8-openjdk-amd64/bin"
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package me.topchetoeu.jscript.filesystem;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
public class FilesystemRegister {
|
||||
private HashMap<String, Filesystem> filesystems = new HashMap<>();
|
||||
}
|
@ -1,86 +0,0 @@
|
||||
package me.topchetoeu.jscript.polyfills;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import me.topchetoeu.jscript.engine.CallContext;
|
||||
import me.topchetoeu.jscript.engine.values.ArrayValue;
|
||||
import me.topchetoeu.jscript.engine.values.FunctionValue;
|
||||
import me.topchetoeu.jscript.engine.values.Values;
|
||||
import me.topchetoeu.jscript.interop.Native;
|
||||
import me.topchetoeu.jscript.interop.NativeGetter;
|
||||
|
||||
public class Map {
|
||||
private LinkedHashMap<Object, Object> objs = new LinkedHashMap<>();
|
||||
|
||||
@Native
|
||||
public Object get(Object key) {
|
||||
return objs.get(key);
|
||||
}
|
||||
@Native
|
||||
public Map set(Object key, Object val) {
|
||||
objs.put(key, val);
|
||||
return this;
|
||||
}
|
||||
@Native
|
||||
public boolean delete(Object key) {
|
||||
if (objs.containsKey(key)) {
|
||||
objs.remove(key);
|
||||
return true;
|
||||
}
|
||||
else return false;
|
||||
}
|
||||
@Native
|
||||
public boolean has(Object key) {
|
||||
return objs.containsKey(key);
|
||||
}
|
||||
|
||||
@Native
|
||||
public void clear() {
|
||||
objs.clear();
|
||||
}
|
||||
|
||||
@Native
|
||||
public void forEach(CallContext ctx, FunctionValue func, Object thisArg) throws InterruptedException {
|
||||
|
||||
for (var el : objs.entrySet().stream().collect(Collectors.toList())) {
|
||||
func.call(ctx, thisArg, el.getValue(), el.getKey(), this);
|
||||
}
|
||||
}
|
||||
|
||||
@Native
|
||||
public Object entries(CallContext ctx) throws InterruptedException {
|
||||
return Values.fromJavaIterable(ctx, objs
|
||||
.entrySet()
|
||||
.stream()
|
||||
.map(v -> new ArrayValue(ctx, v.getKey(), v.getValue()))
|
||||
.collect(Collectors.toList())
|
||||
);
|
||||
}
|
||||
@Native
|
||||
public Object keys(CallContext ctx) throws InterruptedException {
|
||||
return Values.fromJavaIterable(ctx, objs.keySet().stream().collect(Collectors.toList()));
|
||||
}
|
||||
@Native
|
||||
public Object values(CallContext ctx) throws InterruptedException {
|
||||
return Values.fromJavaIterable(ctx, objs.values().stream().collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
@NativeGetter("size")
|
||||
public int size() {
|
||||
return objs.size();
|
||||
}
|
||||
|
||||
@Native
|
||||
public Map(CallContext ctx, Object iterable) throws InterruptedException {
|
||||
if (Values.isPrimitive(iterable)) return;
|
||||
|
||||
for (var val : Values.toJavaIterable(ctx, iterable)) {
|
||||
var first = Values.getMember(ctx, val, 0);
|
||||
var second = Values.getMember(ctx, val, 1);
|
||||
|
||||
set(first, second);
|
||||
}
|
||||
}
|
||||
public Map() { }
|
||||
}
|
@ -1,360 +0,0 @@
|
||||
package me.topchetoeu.jscript.polyfills;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import me.topchetoeu.jscript.engine.CallContext;
|
||||
import me.topchetoeu.jscript.engine.values.ArrayValue;
|
||||
import me.topchetoeu.jscript.engine.values.FunctionValue;
|
||||
import me.topchetoeu.jscript.engine.values.NativeFunction;
|
||||
import me.topchetoeu.jscript.engine.values.ObjectValue;
|
||||
import me.topchetoeu.jscript.engine.values.Values;
|
||||
import me.topchetoeu.jscript.exceptions.EngineException;
|
||||
import me.topchetoeu.jscript.interop.Native;
|
||||
|
||||
public class Promise {
|
||||
private static class Handle {
|
||||
public final CallContext ctx;
|
||||
public final FunctionValue fulfilled;
|
||||
public final FunctionValue rejected;
|
||||
|
||||
public Handle(CallContext ctx, FunctionValue fulfilled, FunctionValue rejected) {
|
||||
this.ctx = ctx;
|
||||
this.fulfilled = fulfilled;
|
||||
this.rejected = rejected;
|
||||
}
|
||||
}
|
||||
|
||||
@Native("resolve")
|
||||
public static Promise ofResolved(CallContext ctx, Object val) {
|
||||
if (Values.isWrapper(val, Promise.class)) return Values.wrapper(val, Promise.class);
|
||||
var res = new Promise();
|
||||
res.fulfill(ctx, val);
|
||||
return res;
|
||||
}
|
||||
public static Promise ofResolved(Object val) {
|
||||
if (Values.isWrapper(val, Promise.class)) return Values.wrapper(val, Promise.class);
|
||||
var res = new Promise();
|
||||
res.fulfill(val);
|
||||
return res;
|
||||
}
|
||||
|
||||
@Native("reject")
|
||||
public static Promise ofRejected(CallContext ctx, Object val) {
|
||||
var res = new Promise();
|
||||
res.reject(ctx, val);
|
||||
return res;
|
||||
}
|
||||
public static Promise ofRejected(Object val) {
|
||||
var res = new Promise();
|
||||
res.fulfill(val);
|
||||
return res;
|
||||
}
|
||||
|
||||
@Native
|
||||
public static Promise any(CallContext ctx, Object _promises) {
|
||||
if (!Values.isArray(_promises)) throw EngineException.ofType("Expected argument for any to be an array.");
|
||||
var promises = Values.array(_promises);
|
||||
if (promises.size() == 0) return ofResolved(new ArrayValue());
|
||||
var n = new int[] { promises.size() };
|
||||
var res = new Promise();
|
||||
|
||||
var errors = new ArrayValue();
|
||||
|
||||
for (var i = 0; i < promises.size(); i++) {
|
||||
var index = i;
|
||||
var val = promises.get(i);
|
||||
if (Values.isWrapper(val, Promise.class)) Values.wrapper(val, Promise.class).then(
|
||||
ctx,
|
||||
new NativeFunction(null, (e, th, args) -> { res.fulfill(e, args[0]); return null; }),
|
||||
new NativeFunction(null, (e, th, args) -> {
|
||||
errors.set(ctx, index, args[0]);
|
||||
n[0]--;
|
||||
if (n[0] <= 0) res.reject(e, errors);
|
||||
return null;
|
||||
})
|
||||
);
|
||||
else {
|
||||
res.fulfill(ctx, val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
@Native
|
||||
public static Promise race(CallContext ctx, Object _promises) {
|
||||
if (!Values.isArray(_promises)) throw EngineException.ofType("Expected argument for any to be an array.");
|
||||
var promises = Values.array(_promises);
|
||||
if (promises.size() == 0) return ofResolved(new ArrayValue());
|
||||
var res = new Promise();
|
||||
|
||||
for (var i = 0; i < promises.size(); i++) {
|
||||
var val = promises.get(i);
|
||||
if (Values.isWrapper(val, Promise.class)) Values.wrapper(val, Promise.class).then(
|
||||
ctx,
|
||||
new NativeFunction(null, (e, th, args) -> { res.fulfill(e, args[0]); return null; }),
|
||||
new NativeFunction(null, (e, th, args) -> { res.reject(e, args[0]); return null; })
|
||||
);
|
||||
else {
|
||||
res.fulfill(val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
@Native
|
||||
public static Promise all(CallContext ctx, Object _promises) {
|
||||
if (!Values.isArray(_promises)) throw EngineException.ofType("Expected argument for any to be an array.");
|
||||
var promises = Values.array(_promises);
|
||||
if (promises.size() == 0) return ofResolved(new ArrayValue());
|
||||
var n = new int[] { promises.size() };
|
||||
var res = new Promise();
|
||||
|
||||
var result = new ArrayValue();
|
||||
|
||||
for (var i = 0; i < promises.size(); i++) {
|
||||
var index = i;
|
||||
var val = promises.get(i);
|
||||
if (Values.isWrapper(val, Promise.class)) Values.wrapper(val, Promise.class).then(
|
||||
ctx,
|
||||
new NativeFunction(null, (e, th, args) -> {
|
||||
result.set(ctx, index, args[0]);
|
||||
n[0]--;
|
||||
if (n[0] <= 0) res.fulfill(e, result);
|
||||
return null;
|
||||
}),
|
||||
new NativeFunction(null, (e, th, args) -> { res.reject(e, args[0]); return null; })
|
||||
);
|
||||
else {
|
||||
result.set(ctx, i, val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (n[0] <= 0) res.fulfill(ctx, result);
|
||||
|
||||
return res;
|
||||
}
|
||||
@Native
|
||||
public static Promise allSettled(CallContext ctx, Object _promises) {
|
||||
if (!Values.isArray(_promises)) throw EngineException.ofType("Expected argument for any to be an array.");
|
||||
var promises = Values.array(_promises);
|
||||
if (promises.size() == 0) return ofResolved(new ArrayValue());
|
||||
var n = new int[] { promises.size() };
|
||||
var res = new Promise();
|
||||
|
||||
var result = new ArrayValue();
|
||||
|
||||
for (var i = 0; i < promises.size(); i++) {
|
||||
var index = i;
|
||||
var val = promises.get(i);
|
||||
if (Values.isWrapper(val, Promise.class)) Values.wrapper(val, Promise.class).then(
|
||||
ctx,
|
||||
new NativeFunction(null, (e, th, args) -> {
|
||||
result.set(ctx, index, new ObjectValue(ctx, Map.of(
|
||||
"status", "fulfilled",
|
||||
"value", args[0]
|
||||
)));
|
||||
n[0]--;
|
||||
if (n[0] <= 0) res.fulfill(e, result);
|
||||
return null;
|
||||
}),
|
||||
new NativeFunction(null, (e, th, args) -> {
|
||||
result.set(ctx, index, new ObjectValue(ctx, Map.of(
|
||||
"status", "rejected",
|
||||
"reason", args[0]
|
||||
)));
|
||||
n[0]--;
|
||||
if (n[0] <= 0) res.fulfill(e, result);
|
||||
return null;
|
||||
})
|
||||
);
|
||||
else {
|
||||
result.set(ctx, i, new ObjectValue(ctx, Map.of(
|
||||
"status", "fulfilled",
|
||||
"value", val
|
||||
)));
|
||||
n[0]--;
|
||||
}
|
||||
}
|
||||
|
||||
if (n[0] <= 0) res.fulfill(ctx, result);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
private List<Handle> handles = new ArrayList<>();
|
||||
|
||||
private static final int STATE_PENDING = 0;
|
||||
private static final int STATE_FULFILLED = 1;
|
||||
private static final int STATE_REJECTED = 2;
|
||||
|
||||
private int state = STATE_PENDING;
|
||||
private Object val;
|
||||
|
||||
/**
|
||||
* Thread safe - call from any thread
|
||||
*/
|
||||
public void fulfill(Object val) {
|
||||
if (Values.isWrapper(val, Promise.class)) throw new IllegalArgumentException("A promise may not be a fulfil value.");
|
||||
if (state != STATE_PENDING) return;
|
||||
|
||||
this.state = STATE_FULFILLED;
|
||||
this.val = val;
|
||||
for (var el : handles) el.ctx.engine().pushMsg(true, el.fulfilled, el.ctx.data(), null, val);
|
||||
handles = null;
|
||||
}
|
||||
/**
|
||||
* Thread safe - call from any thread
|
||||
*/
|
||||
public void fulfill(CallContext ctx, Object val) {
|
||||
if (Values.isWrapper(val, Promise.class)) Values.wrapper(val, Promise.class).then(ctx,
|
||||
new NativeFunction(null, (e, th, args) -> {
|
||||
this.fulfill(e, args[0]);
|
||||
return null;
|
||||
}),
|
||||
new NativeFunction(null, (e, th, args) -> {
|
||||
this.reject(e, args[0]);
|
||||
return null;
|
||||
})
|
||||
);
|
||||
else this.fulfill(val);
|
||||
}
|
||||
/**
|
||||
* Thread safe - call from any thread
|
||||
*/
|
||||
public void reject(Object val) {
|
||||
if (Values.isWrapper(val, Promise.class)) throw new IllegalArgumentException("A promise may not be a reject value.");
|
||||
if (state != STATE_PENDING) return;
|
||||
|
||||
this.state = STATE_REJECTED;
|
||||
this.val = val;
|
||||
for (var el : handles) el.ctx.engine().pushMsg(true, el.rejected, el.ctx.data(), null, val);
|
||||
handles = null;
|
||||
}
|
||||
/**
|
||||
* Thread safe - call from any thread
|
||||
*/
|
||||
public void reject(CallContext ctx, Object val) {
|
||||
if (Values.isWrapper(val, Promise.class)) Values.wrapper(val, Promise.class).then(ctx,
|
||||
new NativeFunction(null, (e, th, args) -> {
|
||||
this.reject(e, args[0]);
|
||||
return null;
|
||||
}),
|
||||
new NativeFunction(null, (e, th, args) -> {
|
||||
this.reject(e, args[0]);
|
||||
return null;
|
||||
})
|
||||
);
|
||||
else this.reject(val);
|
||||
}
|
||||
|
||||
private void handle(CallContext ctx, FunctionValue fulfill, FunctionValue reject) {
|
||||
if (state == STATE_FULFILLED) ctx.engine().pushMsg(true, fulfill, ctx.data(), null, val);
|
||||
else if (state == STATE_REJECTED) ctx.engine().pushMsg(true, reject, ctx.data(), null, val);
|
||||
else handles.add(new Handle(ctx, fulfill, reject));
|
||||
}
|
||||
|
||||
/**
|
||||
* Thread safe - you can call this from anywhere
|
||||
* HOWEVER, it's strongly recommended to use this only in javascript
|
||||
*/
|
||||
@Native
|
||||
public Promise then(CallContext ctx, Object onFulfill, Object onReject) {
|
||||
if (!(onFulfill instanceof FunctionValue)) onFulfill = null;
|
||||
if (!(onReject instanceof FunctionValue)) onReject = null;
|
||||
|
||||
var res = new Promise();
|
||||
|
||||
var fulfill = (FunctionValue)onFulfill;
|
||||
var reject = (FunctionValue)onReject;
|
||||
|
||||
handle(ctx,
|
||||
new NativeFunction(null, (e, th, args) -> {
|
||||
if (fulfill == null) res.fulfill(e, args[0]);
|
||||
else {
|
||||
try { res.fulfill(e, fulfill.call(e, null, args[0])); }
|
||||
catch (EngineException err) { res.reject(e, err.value); }
|
||||
}
|
||||
return null;
|
||||
}),
|
||||
new NativeFunction(null, (e, th, args) -> {
|
||||
if (reject == null) res.reject(e, args[0]);
|
||||
else {
|
||||
try { res.fulfill(e, reject.call(e, null, args[0])); }
|
||||
catch (EngineException err) { res.reject(e, err.value); }
|
||||
}
|
||||
return null;
|
||||
})
|
||||
);
|
||||
|
||||
return res;
|
||||
}
|
||||
/**
|
||||
* Thread safe - you can call this from anywhere
|
||||
* HOWEVER, it's strongly recommended to use this only in javascript
|
||||
*/
|
||||
@Native("catch")
|
||||
public Promise _catch(CallContext ctx, Object onReject) {
|
||||
return then(ctx, null, onReject);
|
||||
}
|
||||
/**
|
||||
* Thread safe - you can call this from anywhere
|
||||
* HOWEVER, it's strongly recommended to use this only in javascript
|
||||
*/
|
||||
@Native("finally")
|
||||
public Promise _finally(CallContext ctx, Object handle) {
|
||||
return then(ctx,
|
||||
new NativeFunction(null, (e, th, args) -> {
|
||||
if (handle instanceof FunctionValue) ((FunctionValue)handle).call(ctx);
|
||||
return args[0];
|
||||
}),
|
||||
new NativeFunction(null, (e, th, args) -> {
|
||||
if (handle instanceof FunctionValue) ((FunctionValue)handle).call(ctx);
|
||||
throw new EngineException(args[0]);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* NOT THREAD SAFE - must be called from the engine executor thread
|
||||
*/
|
||||
@Native
|
||||
public Promise(CallContext ctx, FunctionValue func) throws InterruptedException {
|
||||
if (!(func instanceof FunctionValue)) throw EngineException.ofType("A function must be passed to the promise constructor.");
|
||||
try {
|
||||
func.call(
|
||||
ctx, null,
|
||||
new NativeFunction(null, (e, th, args) -> {
|
||||
fulfill(e, args.length > 0 ? args[0] : null);
|
||||
return null;
|
||||
}),
|
||||
new NativeFunction(null, (e, th, args) -> {
|
||||
reject(e, args.length > 0 ? args[0] : null);
|
||||
return null;
|
||||
})
|
||||
);
|
||||
}
|
||||
catch (EngineException e) {
|
||||
reject(ctx, e.value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override @Native
|
||||
public String toString() {
|
||||
if (state == STATE_PENDING) return "Promise (pending)";
|
||||
else if (state == STATE_FULFILLED) return "Promise (fulfilled)";
|
||||
else return "Promise (rejected)";
|
||||
}
|
||||
|
||||
private Promise(int state, Object val) {
|
||||
this.state = state;
|
||||
this.val = val;
|
||||
}
|
||||
public Promise() {
|
||||
this(STATE_PENDING, null);
|
||||
}
|
||||
}
|
@ -1,76 +0,0 @@
|
||||
package me.topchetoeu.jscript.polyfills;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import me.topchetoeu.jscript.engine.CallContext;
|
||||
import me.topchetoeu.jscript.engine.values.ArrayValue;
|
||||
import me.topchetoeu.jscript.engine.values.FunctionValue;
|
||||
import me.topchetoeu.jscript.engine.values.ObjectValue;
|
||||
import me.topchetoeu.jscript.engine.values.Values;
|
||||
import me.topchetoeu.jscript.exceptions.EngineException;
|
||||
import me.topchetoeu.jscript.interop.Native;
|
||||
import me.topchetoeu.jscript.interop.NativeGetter;
|
||||
|
||||
public class Set {
|
||||
private LinkedHashSet<Object> objs = new LinkedHashSet<>();
|
||||
|
||||
@Native
|
||||
public Set add(Object key) {
|
||||
objs.add(key);
|
||||
return this;
|
||||
}
|
||||
@Native
|
||||
public boolean delete(Object key) {
|
||||
return objs.remove(key);
|
||||
}
|
||||
@Native
|
||||
public boolean has(Object key) {
|
||||
return objs.contains(key);
|
||||
}
|
||||
@Native
|
||||
public void clear() {
|
||||
objs.clear();
|
||||
}
|
||||
|
||||
@Native
|
||||
public void forEach(CallContext ctx, Object func, Object thisArg) throws InterruptedException {
|
||||
if (!(func instanceof FunctionValue)) throw EngineException.ofType("func must be a function.");
|
||||
|
||||
for (var el : objs.stream().collect(Collectors.toList())) {
|
||||
((FunctionValue)func).call(ctx, thisArg, el, el, this);
|
||||
}
|
||||
}
|
||||
|
||||
@Native
|
||||
public ObjectValue entries(CallContext ctx) throws InterruptedException {
|
||||
return Values.fromJavaIterable(ctx, objs
|
||||
.stream()
|
||||
.map(v -> new ArrayValue(ctx, v, v))
|
||||
.collect(Collectors.toList())
|
||||
);
|
||||
}
|
||||
@Native
|
||||
public ObjectValue keys(CallContext ctx) throws InterruptedException {
|
||||
return Values.fromJavaIterable(ctx, objs);
|
||||
}
|
||||
@Native
|
||||
public ObjectValue values(CallContext ctx) throws InterruptedException {
|
||||
return Values.fromJavaIterable(ctx, objs);
|
||||
}
|
||||
|
||||
@NativeGetter("size")
|
||||
public int size() {
|
||||
return objs.size();
|
||||
}
|
||||
|
||||
@Native
|
||||
public Set(CallContext ctx, Object iterable) throws InterruptedException {
|
||||
if (Values.isPrimitive(iterable)) return;
|
||||
|
||||
for (var val : Values.toJavaIterable(ctx, iterable)) {
|
||||
add(val);
|
||||
}
|
||||
}
|
||||
public Set() { }
|
||||
}
|
Loading…
Reference in New Issue
Block a user