Skip to content

Commit

Permalink
Fix crash when loading empty JavaScript file
Browse files Browse the repository at this point in the history
Update documentations the API
Add tool menu to editor plugin to generate typescript project
  • Loading branch information
Geequlim committed Dec 29, 2019
1 parent d6e1360 commit 1efa947
Show file tree
Hide file tree
Showing 6 changed files with 134 additions and 19 deletions.
23 changes: 10 additions & 13 deletions SCsub
Original file line number Diff line number Diff line change
Expand Up @@ -38,22 +38,13 @@ def dump_text_file_to_cpp(file):
source += line
return source

def generate_definition_code():
with open("tools/godot.d.ts.gen.cpp", "w") as f:
text = '/* THIS FILE IS GENERATED DO NOT EDIT */\n#include "editor_tools.h"\nString ECMAScriptPlugin::BUILTIN_DECLEARATION_TEXT = \n${source};';
f.write(text.replace('${source}', dump_text_file_to_cpp("misc/godot.d.ts")))

def generate_script_binding_code():
with open("misc/godot.binding_script.gen.cpp", "w") as f:
text = '/* THIS FILE IS GENERATED DO NOT EDIT */\n#include "../ecmascript_binder.h"\nString ECMAScriptBinder::BINDING_SCRIPT_CONTENT = \n${source};'
f.write(text.replace('${source}', dump_text_file_to_cpp("misc/binding_script.js")))

jsengine = 'quickjs'
if jsengine == 'quickjs':
quickjs()
generate_definition_code()
generate_script_binding_code()

with open("misc/godot.binding_script.gen.cpp", "w") as f:
text = '/* THIS FILE IS GENERATED DO NOT EDIT */\n#include "../ecmascript_binder.h"\nString ECMAScriptBinder::BINDING_SCRIPT_CONTENT = \n${source};'
f.write(text.replace('${source}', dump_text_file_to_cpp("misc/binding_script.js")))

sources = [
'register_types.cpp',
'ecmascript_language.cpp',
Expand All @@ -63,6 +54,12 @@ sources = [
]

if env['tools']:
with open("tools/godot.d.ts.gen.cpp", "w") as f:
text = '/* THIS FILE IS GENERATED DO NOT EDIT */\n#include "editor_tools.h"\nString ECMAScriptPlugin::BUILTIN_DECLEARATION_TEXT = \n${source};';
f.write(text.replace('${source}', dump_text_file_to_cpp("misc/godot.d.ts")))
with open("tools/tsconfig.json.gen.cpp", "w") as f:
text = '/* THIS FILE IS GENERATED DO NOT EDIT */\n#include "editor_tools.h"\nString ECMAScriptPlugin::TSCONFIG_CONTENT = \n${source};'
f.write(text.replace('${source}', dump_text_file_to_cpp("misc/tsconfig.json")))
env_module.add_source_files(env.modules_sources, 'tools/*.cpp')

env_module.Append(CPPPATH=["#modules/ECMAScript"])
Expand Down
102 changes: 97 additions & 5 deletions misc/godot.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,28 +20,115 @@ declare module globalThis {
*/
function cancelAnimationFrame(request_id: FrameRequetID): void;


/**
* The Console API provides functionality to allow developers to perform debugging tasks, such as logging messages or the values of variables at set points in your code, or timing how long an operation takes to complete.
*/
//@ts-ignore
const console: {
/**
* Outputs a message to the console. The message may be a single string (with optional substitution values), or it may be any one or more JavaScript objects.
* @param message A list of JavaScript objects to output. The string representations of each of these objects are appended together in the order listed and output.
*/
log(...message): void;

/**
* Outputs a warning message to the console.
* @param message list of JavaScript objects to output. The string representations of each of these objects are appended together in the order listed and output.
*/
warn(...message): void;

/**
* Outputs an error message to the console.
* @param message A list of JavaScript objects to output. The string representations of each of these objects are appended together in the order listed and output.
*/
error(...message): void;
}

/**
* A worker is an object created using a constructor of `Worker` that runs a named JavaScript file — this file contains the code that will run in the worker thread;
*
* Workers run in another global context that is different from the current context.
*
* You can run whatever code you like inside the worker thread. All of the godot API are avaliable inside workers.
*
* Data is sent between workers and the main thread via a system of messages — both sides send their messages using the `postMessage()` method, and respond to messages via the `onmessage` event handler (the message is contained within the Message event's data attribute.) The data is copied rather than shared.
*
* You can **transfer** value with `Worker.abandonValue` and `Worker.adoptValue`. After a value is abandoned you cannot using it anymore in the context.
*
* Workers may, in turn, spawn new workers, all sub-worker will be stopped when the host context stop.
*/
//@ts-ignore
class Worker {
onmessage(msg: any): void;
postMessage(msg: any): void;

/**
* The `onmessage` property of the Worker interface represents an event handler, that is a function to be called when the message event occurs.
* It will be called when the worker's parent receives a message from the worker context by `postMessage` method.
*/
onmessage(message: any): void;

/**
* Sends a message to the worker's inner scope. This accepts a single parameter, which is the data to send to the worker.
* @param message The object to deliver to the worker; this will be in the data field in the event delivered to the `onmessage` handler.
* @note The data cannot be instance of `godot.Object` or any other JavaScript object conains functions.
*/
postMessage(message: any): void;

/**
* Stop the worker thread
*/
terminate(): void;

/**
* Drop the `value` in the context. You should never touching an abandoned value anymore be for it is adopted.
*
* You can adopt the value in another thread context to transfer the value.
*
* An `non zero` ID is return if no error happen.
* @param value The value to abandon in the context
* @note You can transfer any type the godot `Variant` can represent. But you cannot transfer JavaScript objects with function properties.
* @returns The ID of the abandoned value
*/
static abandonValue(value: any): number;

/**
* Adopt an abandoned value.
* @param value_id The ID of the abandoned value
*/
static adoptValue(value_id: number): any;
}

/** **Worker context only**
*
* Stop the worker thread of current context
*/
function close(): void;

/** **Worker context only**
*
* The message handler to handle messages send from the host context
*/
//@ts-ignore
function onmessage(msg: any): void;
function postMessage(msg: any): void;
function importScripts(...msg: string[]): void;
function onmessage(message: any): void;

/** **Worker context only**
*
* Sends a message to the host thread context that spawned it.
*
* @param {*} message The message to send
*/
function postMessage(message: any): void;

/** **Worker context only**
*
* Synchronously load and run one or more scripts in the worker thread.
*/
function importScripts(...scripts: string[]): void;

/** **Worker context only**
*
* The flag is `true` if current context is inside a worker thread.
*/
const INSIDE_WORKER: true | undefined;
}

Expand Down Expand Up @@ -108,8 +195,13 @@ declare module godot {
const SQRT2: 1.4142135623730950488016887242;
const SQRT12: 0.7071067811865475244008443621048490;

/** The flag is `true` if current binary is compiled with `target=debug` or `target=release_debug` */
const DEBUG_ENABLED: boolean;

/** The flag is `true` if current binary is godot editor which is compiled with `tool=yes` */
const TOOLS_ENABLED: boolean;

/** The flag is `true` if current binary enable debug method information */
const DEBUG_METHODS_ENABLED: boolean;
}

Expand Down
8 changes: 8 additions & 0 deletions misc/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"compilerOptions": {
"module": "ESNext",
"types": [ "godot.d.ts" ],
"lib": [ "ES2020" ],
"allowJs": true
}
}
4 changes: 3 additions & 1 deletion quickjs/quickjs_binder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,9 @@ QuickJSBinder::ModuleCache *QuickJSBinder::js_compile_module(JSContext *ctx, con
CharString code = p_code.utf8();
CharString filename = p_filename.utf8();
const char *cfilename = filename.ptr();
const char *cfilesource = code.ptr();
if (!cfilename) cfilename = ""; // avoid crash with empty file name here
if (!cfilesource) cfilesource = ""; // avoid crash with empty source code here

String md5 = p_code.md5_text();
ModuleCache *last_module = binder->module_cache.getptr(p_filename);
Expand All @@ -437,7 +439,7 @@ QuickJSBinder::ModuleCache *QuickJSBinder::js_compile_module(JSContext *ctx, con
}
}

JSValue func = JS_Eval(ctx, code.ptr(), code.length(), cfilename, JS_EVAL_TYPE_MODULE | JS_EVAL_FLAG_COMPILE_ONLY);
JSValue func = JS_Eval(ctx, cfilesource, code.length(), cfilename, JS_EVAL_TYPE_MODULE | JS_EVAL_FLAG_COMPILE_ONLY);
if (!JS_IsException(func)) {
ModuleCache module;
module.code_md5 = md5;
Expand Down
13 changes: 13 additions & 0 deletions tools/editor_tools.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ void ECMAScriptPlugin::_on_menu_item_pressed(int item) {
case MenuItem::ITEM_GEN_DECLAR_FILE:
declaration_file_dialog->popup_centered_ratio();
break;
case MenuItem::ITEM_GEN_TYPESCRIPT_PROJECT:
_generate_typescript_project();
break;
}
}

Expand All @@ -30,6 +33,7 @@ ECMAScriptPlugin::ECMAScriptPlugin(EditorNode *p_node) {
PopupMenu *menu = memnew(PopupMenu);
add_tool_submenu_item(TTR("ECMAScript"), menu);
menu->add_item(TTR("Generate TypeScript Declaration File"), ITEM_GEN_DECLAR_FILE);
menu->add_item(TTR("Generate TypeScript Project"), ITEM_GEN_TYPESCRIPT_PROJECT);
menu->connect("id_pressed", this, "_on_menu_item_pressed");

declaration_file_dialog = memnew(EditorFileDialog);
Expand Down Expand Up @@ -508,3 +512,12 @@ void ECMAScriptPlugin::_export_typescript_declare_file(const String &p_path) {
f->close();
}
}

void ECMAScriptPlugin::_generate_typescript_project() {
_export_typescript_declare_file("res://godot.d.ts");
FileAccessRef f = FileAccess::open("res://tsconfig.json", FileAccess::WRITE);
if (f.f && f->is_open()) {
f->store_string(TSCONFIG_CONTENT);
f->close();
}
}
3 changes: 3 additions & 0 deletions tools/editor_tools.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,18 @@ class ECMAScriptPlugin : public EditorPlugin {

enum MenuItem {
ITEM_GEN_DECLAR_FILE,
ITEM_GEN_TYPESCRIPT_PROJECT,
};

EditorFileDialog *declaration_file_dialog;

protected:
static String BUILTIN_DECLEARATION_TEXT;
static String TSCONFIG_CONTENT;
static void _bind_methods();
void _on_menu_item_pressed(int item);
void _export_typescript_declare_file(const String &p_path);
void _generate_typescript_project();

public:
virtual String get_name() const { return "ECMAScriptPlugin"; }
Expand Down

0 comments on commit 1efa947

Please sign in to comment.