Compare commits

..

2 Commits

Author SHA1 Message Date
b791f3277e refactor: split up code in 4 modules 2024-01-10 11:21:09 +02:00
5e6e6fea61 feat: some API improvements 2024-01-07 13:40:01 +02:00
196 changed files with 1356 additions and 154 deletions

View File

@@ -16,17 +16,15 @@ jobs:
with:
distribution: 'adopt'
java-version: '11'
- name: Setup Gradle
uses: gradle/gradle-build-action@v2
- name: Clone repository
uses: GuillaumeFalourd/clone-github-repo-action@main
with:
branch: 'master'
branch: 'master' # fuck this political bullshitshit, took me an hour to fix this
owner: 'TopchetoEU'
repository: 'java-jscript'
- name: Build
- name: "Build"
run: |
cd java-jscript; gradle build
cd java-jscript; node ./build.js release ${{ github.ref }}
- uses: "marvinpinto/action-automatic-releases@latest"
with:
@@ -34,4 +32,4 @@ jobs:
prerelease: false
files: |
java-jscript/LICENSE
java-jscript/build/libs/*.jar
java-jscript/dst/*.jar

9
.gitignore vendored
View File

@@ -2,6 +2,7 @@
!/src
!/src/**/*
/src/assets/js/ts.js
!/doc
!/doc/**/*
@@ -9,16 +10,12 @@
!/tests
!/tests/**/*
!/.github
!/.github/**/*
!/.gitignore
!/.gitattributes
!/build.js
!/LICENSE
!/README.md
!/settings.gradle
!/build.gradle
!/gradle.properties
!/gradle
!/gradle/wrapper
!/gradle/wrapper/gradle-wrapper.properties

View File

@@ -11,7 +11,7 @@ JScript is an engine, capable of running EcmaScript 5, written entirely in Java.
The following is going to execute a simple javascript statement:
```java
var engine = new Engine();
var engine = new Engine(false);
// Initialize a standard environment, with implementations of most basic standard libraries (Object, Array, Symbol, etc.)
var env = Internals.apply(new Environment());
@@ -26,4 +26,4 @@ System.out.println(awaitable.await());
## NOTE:
To setup the typescript bundle in your sources, run `node build.js init-ts`. This will download the latest version of typescript, minify it, and add it to your src folder. If you are going to work with the `node build.js debug|release` command, this is not a necessary step.
To setup the typescript bundle in your sources, run `node build.js init-ts`. This will download the latest version of typescript, minify it, and add it to your src/assets folder. If you are going to work with the `node build.js debug|release` command, this is not a necessary step.

View File

@@ -1,32 +0,0 @@
plugins {
id "application"
}
java {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
toolchain.languageVersion = JavaLanguageVersion.of(11)
withSourcesJar()
}
jar {
manifest.attributes["Main-class"] = project.main_class
}
sourceSets {
main.java.srcDirs = [ "src/java" ]
main.resources.srcDirs = [ "src/assets" ]
}
processResources {
filesMatching "metadata.json", {
expand(
version: project.project_version,
name: project.project_name
)
}
}
base.archivesName = project.project_name
version = project.project_version
group = project.project_group

193
build.js Normal file
View File

@@ -0,0 +1,193 @@
const { spawn } = require('child_process');
const fs = require('fs/promises');
const pt = require('path');
const { argv, exit } = require('process');
const { Readable } = require('stream');
async function* find(src, dst, wildcard) {
const stat = await fs.stat(src);
if (stat.isDirectory()) {
for (const el of await fs.readdir(src)) {
for await (const res of find(pt.join(src, el), dst ? pt.join(dst, el) : undefined, wildcard)) yield res;
}
}
else if (stat.isFile() && wildcard(src)) yield dst ? { src, dst } : src;
}
async function copy(src, dst, wildcard) {
const promises = [];
for await (const el of find(src, dst, wildcard)) {
promises.push((async () => {
await fs.mkdir(pt.dirname(el.dst), { recursive: true });
await fs.copyFile(el.src, el.dst);
})());
}
await Promise.all(promises);
}
function run(suppressOutput, cmd, ...args) {
return new Promise((res, rej) => {
const proc = spawn(cmd, args, { stdio: suppressOutput ? 'ignore' : 'inherit' });
proc.once('exit', code => {
if (code === 0) res(code);
else rej(new Error(`Process ${cmd} exited with code ${code}.`));
});
})
}
async function downloadTypescript(outFile) {
try {
// Import the required libraries, without the need of a package.json
console.log('Importing modules...');
await run(true, 'npm', 'i', 'tar', 'zlib', 'uglify-js');
await fs.mkdir(pt.dirname(outFile), { recursive: true });
await fs.mkdir('tmp', { recursive: true });
const tar = require('tar');
const zlib = require('zlib');
const { minify } = await import('uglify-js');
// Download the package.json file of typescript
const packageDesc = await (await fetch('https://registry.npmjs.org/typescript/latest')).json();
const url = packageDesc.dist.tarball;
console.log('Extracting typescript...');
await new Promise(async (res, rej) => Readable.fromWeb((await fetch(url)).body)
.pipe(zlib.createGunzip())
.pipe(tar.x({ cwd: 'tmp', filter: v => v === 'package/lib/typescript.js' }))
.on('end', res)
.on('error', rej)
);
console.log('Compiling typescript to ES5...');
const ts = require('./tmp/package/lib/typescript');
const program = ts.createProgram([ 'tmp/package/lib/typescript.js' ], {
outFile: "tmp/typescript-es5.js",
target: ts.ScriptTarget.ES5,
module: ts.ModuleKind.None,
downlevelIteration: true,
allowJs: true,
});
program.emit();
console.log('Minifying typescript...');
const minified = minify((await fs.readFile('tmp/typescript-es5.js')).toString());
// const minified = { code: (await fs.readFile('tmp/typescript-es5.js')).toString() };
if (minified.error) throw minified.error;
// Patch unsupported regex syntax
minified.code = minified.code.replaceAll('[-/\\\\^$*+?.()|[\\]{}]', '[-/\\\\^$*+?.()|\\[\\]{}]');
const stream = await fs.open(outFile, 'w');
// Write typescript's license
await stream.write(new TextEncoder().encode(`
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at http://www.apache.org/licenses/LICENSE-2.0
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
The following is a minified version of the unmodified Typescript 5.2
***************************************************************************** */
`));
await stream.write(minified.code);
console.log('Typescript bundling done!');
}
finally {
// Clean up all stuff left from typescript bundling
await fs.rm('tmp', { recursive: true, force: true });
await fs.rm('package.json');
await fs.rm('package-lock.json');
await fs.rm('node_modules', { recursive: true });
}
}
async function compileJava(conf) {
try {
await fs.writeFile('Metadata.java', (await fs.readFile('src/me/topchetoeu/jscript/common/Metadata.java')).toString()
.replace('${VERSION}', conf.version)
.replace('${NAME}', conf.name)
.replace('${AUTHOR}', conf.author)
);
const args = ['--release', '11', ];
if (argv[2] === 'debug') args.push('-g');
args.push('-d', 'dst/classes', 'Metadata.java');
console.log('Compiling java project...');
for await (const path of find('src', undefined, v => v.endsWith('.java') && !v.endsWith('Metadata.java'))) args.push(path);
await run(false, conf.javahome + 'javac', ...args);
console.log('Compiled java project!');
}
finally {
await fs.rm('Metadata.java');
}
}
async function jar(conf, project, mainClass) {
const args = [
'jar', '-c',
'-f', `dst/${project}-v${conf.version}.jar`,
];
if (mainClass) args.push('-e', mainClass);
args.push('-C', 'dst/classes', project.replaceAll('.', '/'));
console.log(args.join(' '));
await run(true, ...args);
}
(async () => {
try {
if (argv[2] === 'init-ts') {
await downloadTypescript('src/me/topchetoeu/jscript/utils/assets/js/ts.js');
}
else {
const conf = {
name: "java-jscript",
author: "TopchetoEU",
javahome: "",
version: argv[3]
};
if (conf.version.startsWith('refs/tags/')) conf.version = conf.version.substring(10);
if (conf.version.startsWith('v')) conf.version = conf.version.substring(1);
try { await fs.rm('dst', { recursive: true }); } catch {}
await Promise.all([
(async () => {
await copy('src', 'dst/classes', v => !v.endsWith('.java'));
// await downloadTypescript('dst/classes/me/topchetoeu/jscript/utils/assets/js/ts.js');
})(),
compileJava(conf),
]);
await Promise.all([
jar(conf, 'me.topchetoeu.jscript.common'),
jar(conf, 'me.topchetoeu.jscript.core'),
jar(conf, 'me.topchetoeu.jscript.lib'),
jar(conf, 'me.topchetoeu.jscript.utils'),
jar(conf, 'me.topchetoeu.jscript', 'me.topchetoeu.jscript.utils.JScriptRepl'),
]);
console.log('Done!');
}
}
catch (e) {
if (argv[2] === 'debug') throw e;
console.log(e.toString());
exit(-1);
}
})();

View File

@@ -1,4 +0,0 @@
project_group = me.topchetoeu
project_name = jscript
project_version = 0.8.6-beta
main_class = me.topchetoeu.jscript.utils.JScriptRepl

View File

@@ -1,7 +0,0 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

View File

@@ -1,5 +0,0 @@
plugins {
id 'org.gradle.toolchains.foojay-resolver-convention' version '0.7.0'
}
rootProject.name = properties.project_name

View File

@@ -1,5 +0,0 @@
{
"version": "${version}",
"name": "${name}",
"author": "TopchetoEU"
}

View File

@@ -1,36 +0,0 @@
package me.topchetoeu.jscript.lib;
import java.io.IOException;
import java.io.OutputStream;
import me.topchetoeu.jscript.core.engine.values.Values;
import me.topchetoeu.jscript.utils.filesystem.FilesystemException;
import me.topchetoeu.jscript.utils.filesystem.FilesystemException.FSCode;
import me.topchetoeu.jscript.utils.interop.Arguments;
import me.topchetoeu.jscript.utils.interop.Expose;
import me.topchetoeu.jscript.utils.interop.WrapperName;
@WrapperName("Console")
public class ConsoleLib {
private final OutputStream stream;
@Expose
public void __log(Arguments args) {
try {
var first = true;
for (var el : args.args) {
if (!first) stream.write(" ".getBytes());
first = false;
stream.write(Values.toReadable(args.ctx, el).getBytes());
}
stream.write((byte)'\n');
}
catch (IOException e) {
throw new FilesystemException("stdout", FSCode.NO_PERMISSIONS_RW);
}
}
public ConsoleLib(OutputStream stream) {
this.stream = stream;
}
}

View File

@@ -1,7 +0,0 @@
package me.topchetoeu.jscript.utils.debug;
import me.topchetoeu.jscript.core.engine.debug.DebugController;
public interface Debugger extends DebugHandler, DebugController {
void close();
}

View File

@@ -1,18 +1,9 @@
package me.topchetoeu.jscript.common;
import me.topchetoeu.jscript.common.json.JSON;
public class Metadata {
private static final String VERSION;
private static final String AUTHOR;
private static final String NAME;
static {
var data = JSON.parse(null, Reading.resourceToString("metadata.json")).map();
VERSION = data.string("version");
AUTHOR = data.string("author");
NAME = data.string("name");
}
private static final String VERSION = "${VERSION}";
private static final String AUTHOR = "${AUTHOR}";
private static final String NAME = "${NAME}";
public static String version() {
if (VERSION.equals("$" + "{VERSION}")) return "1337-devel";

View File

@@ -1,4 +1,4 @@
package me.topchetoeu.jscript.utils.debug;
package me.topchetoeu.jscript.core.engine.debug;
import java.io.IOException;

View File

@@ -1,4 +1,4 @@
package me.topchetoeu.jscript.utils.debug;
package me.topchetoeu.jscript.core.engine.debug;
import java.io.IOException;
import java.io.UncheckedIOException;
@@ -15,7 +15,7 @@ import me.topchetoeu.jscript.common.events.Notifier;
import me.topchetoeu.jscript.common.json.JSON;
import me.topchetoeu.jscript.common.json.JSONList;
import me.topchetoeu.jscript.common.json.JSONMap;
import me.topchetoeu.jscript.utils.debug.WebSocketMessage.Type;
import me.topchetoeu.jscript.core.engine.debug.WebSocketMessage.Type;
import me.topchetoeu.jscript.core.exceptions.SyntaxException;
public class DebugServer {
@@ -226,9 +226,9 @@ public class DebugServer {
public DebugServer() {
try {
this.favicon = Reading.resourceToStream("debugger/favicon.png").readAllBytes();
this.protocol = Reading.resourceToStream("debugger/protocol.json").readAllBytes();
this.index = Reading.resourceToString("debugger/index.html")
this.favicon = Reading.resourceToStream("me/topchetoeu/jscript/utils/assets/debugger/favicon.png").readAllBytes();
this.protocol = Reading.resourceToStream("me/topchetoeu/jscript/utils/assets/debugger/protocol.json").readAllBytes();
this.index = Reading.resourceToString("me/topchetoeu/jscript/utils/assets/debugger/index.html")
.replace("${NAME}", Metadata.name())
.replace("${VERSION}", Metadata.version())
.replace("${AUTHOR}", Metadata.author())

View File

@@ -0,0 +1,5 @@
package me.topchetoeu.jscript.core.engine.debug;
public interface Debugger extends DebugHandler, DebugController {
void close();
}

View File

@@ -1,4 +1,4 @@
package me.topchetoeu.jscript.utils.debug;
package me.topchetoeu.jscript.core.engine.debug;
public interface DebuggerProvider {
Debugger getDebugger(WebSocket socket, HttpRequest req);

View File

@@ -1,4 +1,4 @@
package me.topchetoeu.jscript.utils.debug;
package me.topchetoeu.jscript.core.engine.debug;
import java.io.BufferedReader;
import java.io.IOException;

View File

@@ -1,4 +1,4 @@
package me.topchetoeu.jscript.utils.debug;
package me.topchetoeu.jscript.core.engine.debug;
import java.io.IOException;
import java.util.ArrayList;
@@ -22,7 +22,6 @@ import me.topchetoeu.jscript.core.compilation.Instruction.Type;
import me.topchetoeu.jscript.core.engine.Context;
import me.topchetoeu.jscript.core.engine.Engine;
import me.topchetoeu.jscript.core.engine.Environment;
import me.topchetoeu.jscript.core.engine.debug.DebugContext;
import me.topchetoeu.jscript.core.engine.frame.CodeFrame;
import me.topchetoeu.jscript.core.engine.scope.GlobalScope;
import me.topchetoeu.jscript.core.engine.values.ArrayValue;

View File

@@ -1,4 +1,4 @@
package me.topchetoeu.jscript.utils.debug;
package me.topchetoeu.jscript.core.engine.debug;
import me.topchetoeu.jscript.common.json.JSON;
import me.topchetoeu.jscript.common.json.JSONMap;

View File

@@ -1,4 +1,4 @@
package me.topchetoeu.jscript.utils.debug;
package me.topchetoeu.jscript.core.engine.debug;
import me.topchetoeu.jscript.common.json.JSON;
import me.topchetoeu.jscript.common.json.JSONMap;

View File

@@ -1,4 +1,4 @@
package me.topchetoeu.jscript.utils.debug;
package me.topchetoeu.jscript.core.engine.debug;
import java.util.Map;

View File

@@ -1,4 +1,4 @@
package me.topchetoeu.jscript.utils.debug;
package me.topchetoeu.jscript.core.engine.debug;
import me.topchetoeu.jscript.common.json.JSON;
import me.topchetoeu.jscript.common.json.JSONMap;

View File

@@ -1,4 +1,4 @@
package me.topchetoeu.jscript.utils.debug;
package me.topchetoeu.jscript.core.engine.debug;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@@ -6,7 +6,7 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import me.topchetoeu.jscript.utils.debug.WebSocketMessage.Type;
import me.topchetoeu.jscript.core.engine.debug.WebSocketMessage.Type;
public class WebSocket implements AutoCloseable {
public long maxLength = 1 << 20;

View File

@@ -1,4 +1,4 @@
package me.topchetoeu.jscript.utils.debug;
package me.topchetoeu.jscript.core.engine.debug;
public class WebSocketMessage {
public static enum Type {

Some files were not shown because too many files have changed in this diff Show More