Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 87 additions & 29 deletions src/lang/lang_typescript.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -170,40 +170,19 @@ struct WrapParam
{
return "Deno.PointerValue";
}
if (func.return_type == "int" || func.return_type == "TArrayLen" ||
func.return_type == "TByteStringLen")
{
return "number";
}
if (func.return_type == "long" || func.return_type == "time_t")
{
return "number";
}
if (func.return_type == "unsigned" || func.return_type == "unsigned int")
{
return "number";
}
if (func.return_type == "unsigned long" || func.return_type == "wxUIntPtr")
if (func.return_type == "void*" || func.return_type.find('*') != std::string::npos)
{
return "number";
return "Deno.PointerValue";
}
if (func.return_type == "uintptr_t" || func.return_type == "size_t")
{
return "bigint";
}
if (func.return_type == "double" || func.return_type == "float")
{
return "number";
}
if (func.return_type == "TChar" || func.return_type == "TUInt8")
{
return "number";
}
if (func.return_type == "void*" || func.return_type.find('*') != std::string::npos)
{
return "Deno.PointerValue";
}
return "number"; // fallback

// All remaining numeric types (int, long, unsigned, unsigned long, double,
// float, TArrayLen, TByteStringLen, TChar, TUInt8, time_t, wxUIntPtr, etc.)
// map to the Deno FFI "number" type.
return "number";
}

// Emit the return statement for a method wrapper, applying any needed conversions.
Expand Down Expand Up @@ -296,6 +275,7 @@ void TypeScriptEmitter::Generate(const ParsedFFI& ffi, const fs::path& out_dir)

GenerateFfi(ffi, out_dir);
GenerateConstants(ffi, out_dir);
GenerateHelpers(out_dir);
GenerateFreeFunctions(ffi, out_dir);
GenerateClassFiles(ffi, out_dir);
GenerateIndex(ffi, out_dir);
Expand Down Expand Up @@ -333,7 +313,9 @@ void TypeScriptEmitter::GenerateFfi(const ParsedFFI& ffi, const fs::path& out_di
output << "export const lib = Deno.dlopen(_libName, {\n";

// Class methods
std::unordered_set<std::string> emitted_symbols;
size_t method_count = 0;
size_t free_count = 0;
for (const auto& cls: ffi.classes)
{
for (const auto& func: cls.methods)
Expand All @@ -342,6 +324,11 @@ void TypeScriptEmitter::GenerateFfi(const ParsedFFI& ffi, const fs::path& out_di
{
continue;
}
const std::string func_name = CFuncName(func);
if (!emitted_symbols.insert(func_name).second)
{
continue;
}
EmitSymbolDef(output, func);
++method_count;
}
Expand All @@ -354,7 +341,13 @@ void TypeScriptEmitter::GenerateFfi(const ParsedFFI& ffi, const fs::path& out_di
{
continue;
}
const std::string func_name = CFuncName(func);
if (!emitted_symbols.insert(func_name).second)
{
continue;
}
EmitSymbolDef(output, func);
++free_count;
}

// Event accessor symbols (no parameters, return i32)
Expand All @@ -378,15 +371,78 @@ void TypeScriptEmitter::GenerateFfi(const ParsedFFI& ffi, const fs::path& out_di
<< " },\n";
}

// Always-available kwxFFI symbols (string buffer utilities)
if (emitted_symbols.insert("kwxUtf8Buffer_Create").second)
{
output << " kwxUtf8Buffer_Create: { parameters: [\"pointer\"], result: \"pointer\" },\n";
}
if (emitted_symbols.insert("kwxUtf8Buffer_Data").second)
{
output << " kwxUtf8Buffer_Data: { parameters: [\"pointer\"], result: \"pointer\" },\n";
}
if (emitted_symbols.insert("kwxUtf8Buffer_Delete").second)
{
output << " kwxUtf8Buffer_Delete: { parameters: [\"pointer\"], result: \"void\" },\n";
}

output << "} as const);\n";

std::println(stderr,
" kwx_ffi_gen.ts: {} class methods, {} free functions, "
"{} events, {} keys, {} constants",
method_count, ffi.free_functions.size(), ffi.events.size(), ffi.keys.size(),
method_count, free_count, ffi.events.size(), ffi.keys.size(),
ffi.constants.size());
}

// -------------------------------------------------------------------------
// kwx_helpers_gen.ts — wxString conversion utilities for generated code
// -------------------------------------------------------------------------

void TypeScriptEmitter::GenerateHelpers(const fs::path& out_dir)
{
const fs::path file_path = out_dir / "kwx_helpers_gen.ts";
ConditionalFileWriter output(file_path);

WriteGeneratedHeader(output, "//");
output <<
R"TS(import { lib } from "./kwx_ffi_gen.ts";
import { wxString } from "./wxString_gen.ts";

// --- Helper: create a wxString from a JS string ---
export function createWxString(s: string): wxString
{
const buf = new TextEncoder().encode(s + "\0");
const ptr = Deno.UnsafePointer.of(buf);
const result = wxString.CreateUTF8(ptr);
if (!result)
{
throw new Error(`Failed to create wxString for: ${s}`);
}
return result;
}

// --- Helper: read a JS string from a wxString* ---
export function readWxString(wxStrPtr: Deno.PointerValue): string
{
const buf = lib.symbols.kwxUtf8Buffer_Create(wxStrPtr);
const data = lib.symbols.kwxUtf8Buffer_Data(buf);
const result = data ? Deno.UnsafePointerView.getCString(data) : "";
lib.symbols.kwxUtf8Buffer_Delete(buf);
return result;
}

// --- Helper: read and delete a wxString* returned from a getter ---
export function readAndDeleteWxString(wxStrPtr: Deno.PointerValue): string
{
const result = readWxString(wxStrPtr);
lib.symbols.wxString_Delete(wxStrPtr);
return result;
}
)TS";

std::println(stderr, " kwx_helpers_gen.ts: wxString conversion helpers");
}

// -------------------------------------------------------------------------
// kwx_constants_gen.ts — eagerly-evaluated constants, events, and keys
// -------------------------------------------------------------------------
Expand Down Expand Up @@ -812,6 +868,8 @@ void TypeScriptEmitter::GenerateIndex(const ParsedFFI& ffi, const fs::path& out_
output << "export * from \"./kwx_free_functions_gen.ts\";\n";
}

output << "export * from \"./kwx_helpers_gen.ts\";\n";

// Sort class names for deterministic output
std::vector<std::string> class_names;
for (const auto& cls: ffi.classes)
Expand Down
3 changes: 3 additions & 0 deletions src/lang/lang_typescript.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,7 @@ class TypeScriptEmitter : public LanguageEmitter

// Emits the body of a single TypeScript class wrapper file.
static void EmitClassFile(std::ostream& output, const ClassInfo& cls, const ParsedFFI& ffi);

// Emits kwx_helpers_gen.ts — wxString conversion utilities for generated code.
static void GenerateHelpers(const std::filesystem::path& out_dir);
};
Loading