mirror of
https://github.com/DarkFlippers/unleashed-firmware.git
synced 2025-12-12 12:42:30 +04:00
* JS: Fix file select for fbt launch js_app * JS: badusb: Add numpad keys Co-authored-by: oldip <oldip@users.noreply.github.com> * JS: badusb: Layout support * JS: badusb: altPrint() and altPrintln() Co-authored-by: oldip <oldip@users.noreply.github.com> * JS: badusb: quit() * JS: serial: readAny() * JS: serial: end() * JS: serial: Auto disable expansion service * JS: storage: Add example script * JS: gui: text_input: Fix NULL ptr when no prop given * JS: gui: text_input: Default text props Co-authored-by: xMasterX <xMasterX@users.noreply.github.com> * JS: gui: byte_input Co-authored-by: xMasterX <xMasterX@users.noreply.github.com> * JS: gui: file_picker * JS: gui: viewDispatcher.currentView * JS: gui: view.hasProperty() * JS: gui: Add some missing typedefs comments * JS: globals: Fix toString() with negative numbers * JS: globals: parseInt() Co-authored-by: Spooks4576 <Spooks4576@users.noreply.github.com> * JS: globals: toUpperCase() and toLowerCase() Co-authored-by: Spooks4576 <Spooks4576@users.noreply.github.com> * JS: globals: Add some missing typedefs * JS: Add example for string functions Co-authored-by: Spooks4576 <Spooks4576@users.noreply.github.com> * JS: globals: __dirpath and __filepath Co-authored-by: jamisonderek <jamisonderek@users.noreply.github.com> * JS: globals: load() typedef missing scope param * JS: Add interactive REPL script example * JS: Add missing icon for file picker * JS: Rename to __filename and __dirname * JS: Move toUpperCase() and toLowerCase() to string class * JS: parseInt() refactor * JS: Typedef base param for parseInt() * Revert "JS: gui: view.hasProperty()" This reverts commit 1967ec06d4f2e9cafc4e18384ad370f7a7c44468. * JS: Move toString() to Number class * JS: Fix duplicate plugin files in plugins, `requires` is used to determine which app to distribute the .fal under `apps_data/appid/plugins` * JS: math: Missing typedefs, use camelCase * JS: badusb: layoutPath is optional in typedef * Fix ASS scoping * Rename mjs term prop type value * Change load() description * Enlarge buffers in default prop assign * More checks for default data/text size * Make PVS happy * Fix icon symbol * Update types for JS SDK * toString() was moved to number class Co-authored-by: oldip <oldip@users.noreply.github.com> Co-authored-by: xMasterX <xMasterX@users.noreply.github.com> Co-authored-by: Spooks4576 <Spooks4576@users.noreply.github.com> Co-authored-by: jamisonderek <jamisonderek@users.noreply.github.com> Co-authored-by: hedger <hedger@users.noreply.github.com> Co-authored-by: あく <alleteam@gmail.com>
94 lines
3.2 KiB
JavaScript
94 lines
3.2 KiB
JavaScript
let eventLoop = require("event_loop");
|
|
let gui = require("gui");
|
|
let dialog = require("gui/dialog");
|
|
let textInput = require("gui/text_input");
|
|
let loading = require("gui/loading");
|
|
let storage = require("storage");
|
|
|
|
// No eval() or exec() so need to run code from file, and filename must be unique
|
|
storage.makeDirectory("/ext/.tmp");
|
|
storage.makeDirectory("/ext/.tmp/js");
|
|
storage.rmrf("/ext/.tmp/js/repl")
|
|
storage.makeDirectory("/ext/.tmp/js/repl")
|
|
let ctx = {
|
|
tmpTemplate: "/ext/.tmp/js/repl/",
|
|
tmpNumber: 0,
|
|
persistentScope: {},
|
|
};
|
|
|
|
let views = {
|
|
dialog: dialog.makeWith({
|
|
header: "Interactive Console",
|
|
text: "Press OK to Start",
|
|
center: "Run Some JS"
|
|
}),
|
|
textInput: textInput.makeWith({
|
|
header: "Type JavaScript Code:",
|
|
minLength: 0,
|
|
maxLength: 256,
|
|
defaultText: "2+2",
|
|
defaultTextClear: true,
|
|
}),
|
|
loading: loading.make(),
|
|
};
|
|
|
|
eventLoop.subscribe(views.dialog.input, function (_sub, button, gui, views) {
|
|
if (button === "center") {
|
|
gui.viewDispatcher.switchTo(views.textInput);
|
|
}
|
|
}, gui, views);
|
|
|
|
eventLoop.subscribe(views.textInput.input, function (_sub, text, gui, views, ctx) {
|
|
gui.viewDispatcher.switchTo(views.loading);
|
|
|
|
let path = ctx.tmpTemplate + (ctx.tmpNumber++).toString();
|
|
let file = storage.openFile(path, "w", "create_always");
|
|
file.write(text);
|
|
file.close();
|
|
|
|
// Hide GUI before running, we want to see console and avoid deadlock if code fails
|
|
gui.viewDispatcher.sendTo("back");
|
|
let result = load(path, ctx.persistentScope); // Load runs JS and returns last value on stack
|
|
storage.remove(path);
|
|
|
|
// Must convert to string explicitly
|
|
if (result === null) { // mJS: typeof null === "null", ECMAScript: typeof null === "object", IDE complains when checking "null" type
|
|
result = "null";
|
|
} else if (typeof result === "string") {
|
|
result = "'" + result + "'";
|
|
} else if (typeof result === "number") {
|
|
result = result.toString();
|
|
} else if (typeof result === "bigint") { // mJS doesn't support BigInt() but might aswell check
|
|
result = "bigint";
|
|
} else if (typeof result === "boolean") {
|
|
result = result ? "true" : "false";
|
|
} else if (typeof result === "symbol") { // mJS doesn't support Symbol() but might aswell check
|
|
result = "symbol";
|
|
} else if (typeof result === "undefined") {
|
|
result = "undefined";
|
|
} else if (typeof result === "object") {
|
|
result = "object"; // JSON.stringify() is not implemented
|
|
} else if (typeof result === "function") {
|
|
result = "function";
|
|
} else {
|
|
result = "unknown type: " + typeof result;
|
|
}
|
|
|
|
gui.viewDispatcher.sendTo("front");
|
|
views.dialog.set("header", "JS Returned:");
|
|
views.dialog.set("text", result);
|
|
gui.viewDispatcher.switchTo(views.dialog);
|
|
views.textInput.set("defaultText", text);
|
|
}, gui, views, ctx);
|
|
|
|
eventLoop.subscribe(gui.viewDispatcher.navigation, function (_sub, _, eventLoop) {
|
|
eventLoop.stop();
|
|
}, eventLoop);
|
|
|
|
gui.viewDispatcher.switchTo(views.dialog);
|
|
|
|
// Message behind GUI if something breaks
|
|
print("If you're stuck here, something went wrong, re-run the script")
|
|
eventLoop.run();
|
|
print("\n\nFinished correctly :)")
|