Skip to content

Commit

Permalink
Optimizing Core
Browse files Browse the repository at this point in the history
- Removing all external modules
- Make module compatible with `deno compile`
- Updating readme (simpler)
  • Loading branch information
hassandraga committed Nov 24, 2023
1 parent ce838ad commit a29dfb0
Show file tree
Hide file tree
Showing 8 changed files with 110 additions and 89 deletions.
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ src/webui-linux-gcc-arm64/
*.so
*.dylib

# Archives
*.zip
*.tar
*.gz

# Build
*.exe
*.ilk
Expand Down
30 changes: 5 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<div align="center">

![Logo](https://github.com/webui-dev/deno-webui/assets/34311583/c92e712f-0698-486a-a460-d4acea28a4f8)
![Logo](img/webui.png)

# Deno WebUI v2.4.0

Expand All @@ -14,7 +14,7 @@

> WebUI is not a web-server solution or a framework, but it allows you to use any web browser as a GUI, with your preferred language in the backend and HTML5 in the frontend. All in a lightweight portable lib.
![Screenshot](https://github.com/webui-dev/webui/assets/34311583/57992ef1-4f7f-4d60-8045-7b07df4088c6)
![Screenshot](img/screenshot.png)

</div>

Expand All @@ -34,7 +34,7 @@

## Screenshot

This [text editor example](https://github.com/webui-dev/deno-webui/tree/main/examples)
This [hello world example](https://github.com/webui-dev/deno-webui/tree/main/examples/hello_world)
is written in Deno using WebUI as the GUI library.

![ScreenShot](img/webui_deno_example.png)
Expand All @@ -49,39 +49,19 @@ is written in Deno using WebUI as the GUI library.
import { WebUI } from "https://deno.land/x/webui/mod.ts";

const myWindow = new WebUI();
webui.show("<html>Hello World</html>");
webui.show("<html><script src="webui.js"></script> Hello World! </html>");
await WebUI.wait();
```

## Examples

- Hello world example:
```sh
deno run -A --unstable https://deno.land/x/webui/examples/hello_world/hello_world.ts
deno run --allow-all --unstable hello_world.ts
```

[More examples](https://github.com/webui-dev/deno-webui/tree/main/examples)

## Security flags

Minimal required flags for running the module are:

| flag | value | purpose |
| ----------- | -------------------------------------- | ---------------------------------------- |
| unstable | NA | FFI UnsafePointer and UnsafeCallback use |
| allow-env | USERPROFILE (windows) or HOME (others) | Caching dynamic library |
| allow-write | ~/.deno_webui | Saving cache |
| allow-read | ~/.deno_webui | Opening cache |
| allow-ffi | ~/.deno_webui (unstable so allow all) | Using FFI |

Example:

```sh
deno run --unstable --allow-env=HOME --allow-ffi --allow-read=~/.deno_webui --allow-write=~/.deno_webui https://deno.land/x/webui/examples/hello_world/hello_world.ts
```

You can see all permissions prompt by using `deno run` without any.

## Documentation

- [Online Documentation](https://webui.me/docs/#/deno_api)
Expand Down
33 changes: 19 additions & 14 deletions deps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ async function getLibName() {
case "x86_64":
fileName = "webui-windows-msvc-x64/webui-2.dll";
break;
case "arm":
fileName = "webui-windows-msvc-arm/webui-2.dll";
break;
case "arm64":
// case "arm":
// fileName = "webui-windows-msvc-arm/webui-2.dll";
// break;
// case "arm64":
case "aarch64":
fileName = "webui-windows-msvc-arm64/webui-2.dll";
break;
Expand All @@ -35,10 +35,10 @@ async function getLibName() {
case "x86_64":
fileName = "webui-macos-clang-x64/webui-2.dylib";
break;
case "arm":
fileName = "webui-macos-clang-arm/webui-2.dylib";
break;
case "arm64":
// case "arm":
// fileName = "webui-macos-clang-arm/webui-2.dylib";
// break;
// case "arm64":
case "aarch64":
fileName = "webui-macos-clang-arm64/webui-2.dylib";
break;
Expand All @@ -49,21 +49,26 @@ async function getLibName() {
}
break;
default:
// Assuming Linux for default
// Linux
// freebsd
// netbsd
// aix
// solaris
// illumos
switch (Deno.build.arch) {
case "x86_64":
fileName = "webui-linux-gcc-x64/webui-2.so";
break;
case "arm":
fileName = "webui-linux-gcc-arm/webui-2.so";
break;
case "arm64":
// case "arm":
// fileName = "webui-linux-gcc-arm/webui-2.so";
// break;
// case "arm64":
case "aarch64":
fileName = "webui-linux-gcc-arm64/webui-2.so";
break;
default:
throw new Error(
`Unsupported architecture ${Deno.build.arch} for Linux`,
`Unsupported architecture ${Deno.build.arch} for ${Deno.build.os}`,
);
}
break;
Expand Down
2 changes: 1 addition & 1 deletion examples/hello_world/hello_world.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ const myHtml = `
</style>
</head>
<body>
<h1>WebUI 2 - Deno Hello World (File)</h1><br>
<h1>WebUI 2 - Deno Hello World</h1><br>
A: <input id="MyInputA" value="4"><br><br>
B: <input id="MyInputB" value="6"><br><br>
<div id="Result" style="color: #dbdd52">Result: ?</div><br><br>
Expand Down
Binary file added img/webui.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified img/webui_deno_example.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
100 changes: 62 additions & 38 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,52 @@
// Deno WebUI
// Utilities

import * as path from "https://deno.land/std/path/mod.ts";
import { ensureDir, move } from "https://deno.land/std/fs/mod.ts";
import { BlobReader, BlobWriter, ZipReader } from "https://deno.land/x/zipjs/index.js";
// Combine paths
function joinPath(...segments: string[]): string {
const isWindows = Deno.build.os === "windows";
const separator = isWindows ? "\\" : "/";
let joinedPath = segments
.join(separator) // Join all segments with the OS-specific separator
.replace(/[\/\\]+/g, separator); // Replace multiple separators with a single one
return joinedPath;
}

// Download a file from Internet
async function downloadFile(url: string, dest: string) {
const res = await fetch(url);
const fileData = new Uint8Array(await res.arrayBuffer());
await Deno.writeFile(dest, fileData);
}

// Run a system command
async function runCommand(command: string[]): Promise<void> {
const process = Deno.run({
cmd: command,
stdout: "null",
stderr: "null",
});
await process.status();
process.close();
}

// Create a directory
async function createDirectory(dirPath: string): Promise<void> {
const isWindows = Deno.build.os === "windows";
const command = isWindows ? ["cmd", "/c", "mkdir", dirPath] : ["mkdir", "-p", dirPath];
await runCommand(command);
}

// Copy file and overwrite
async function copyFileOverwrite(srcPath: string, destPath: string) {
try {
await Deno.remove(destPath);
} catch (error) {
if (!(error instanceof Deno.errors.NotFound)) {
throw error;
}
}
await Deno.copyFile(srcPath, destPath);
}

// Get current module full folder path
export const currentModulePath = (() => {
Expand All @@ -19,9 +62,9 @@ export const currentModulePath = (() => {
})();

// Check if a file exist
export async function fileExists(path) {
export async function fileExists(filePath: string) {
try {
await Deno.stat(path);
await Deno.stat(filePath);
return true;
} catch (error) {
if (error instanceof Deno.errors.NotFound) {
Expand All @@ -32,32 +75,6 @@ export async function fileExists(path) {
}
}

// Download a file from Internet
async function downloadFile(url: string, dest: string) {
const res = await fetch(url);
const fileData = new Uint8Array(await res.arrayBuffer());
await Deno.writeFile(dest, fileData);
}

// Uncompress a .Zip archive
async function unzipFile(zipFilePath: string, outputDir: string) {
const zipFileData = await Deno.readFile(zipFilePath);
const zipFileReader = new BlobReader(new Blob([zipFileData]));
const zipReader = new ZipReader(zipFileReader);
const entries = await zipReader.getEntries();
for (const entry of entries) {
const fullPath = path.join(outputDir, entry.filename);
if (entry.directory) {
await ensureDir(fullPath);
} else {
const entryWriter = new BlobWriter();
const entryData = await entry.getData(entryWriter);
await Deno.writeFile(fullPath, new Uint8Array(await entryData.arrayBuffer()));
}
}
await zipReader.close();
}

export async function downloadCoreLibrary() {
// Base URL
const baseUrl = "https://github.com/webui-dev/webui/releases/download/nightly/";
Expand Down Expand Up @@ -95,25 +112,32 @@ export async function downloadCoreLibrary() {
}

// Construct file name and download URL
const cacheDir = path.join(currentModulePath, `cache`);
const cacheDir = joinPath(currentModulePath, `cache`);
const fileName = `webui-${os}-${cc}-${arch}`;
const fileUrl = `${baseUrl}${fileName}.zip`;
const outputDir = path.join(currentModulePath, fileName);
const outputDir = joinPath(currentModulePath, fileName);

// Create cache directory
await ensureDir(cacheDir);
await createDirectory(cacheDir);

// Download the archive
const zipPath = path.join(cacheDir, `${fileName}.zip`);
const zipPath = joinPath(cacheDir, `${fileName}.zip`);
await downloadFile(fileUrl, zipPath);

// Extract the archive
await unzipFile(zipPath, cacheDir);
switch (Deno.build.os) {
case "windows":
await runCommand(["tar", "-xf", zipPath, "-C", cacheDir]);
break;
default:
await runCommand(["unzip", "-q", zipPath, "-d", cacheDir]);
break;
}

// Copy library
const libFile = `webui-2.${ext}`;
await ensureDir(outputDir);
await Deno.copyFile(path.join(cacheDir, fileName, libFile), path.join(outputDir, libFile), { overwrite: true });
await createDirectory(outputDir);
await copyFileOverwrite(joinPath(cacheDir, fileName, libFile), joinPath(outputDir, libFile));

// Remove cache directory
await Deno.remove(cacheDir, { recursive: true });
Expand Down
29 changes: 18 additions & 11 deletions src/webui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -292,28 +292,35 @@ export class WebUI {
id: string,
callback: BindCallback<T>,
) {
// Create the callback
const callbackResource = new Deno.UnsafeCallback(
{
// size_t webui_interface_bind(..., void (*func)(size_t, size_t, char*, size_t, size_t))
// func (Window, EventType, Element, EventNumber, BindID)
// func = (Window, EventType, Element, EventNumber, BindID)
parameters: ["usize", "usize", "pointer", "usize", "usize"],
result: "void",
} as const,
async (
param_window: number,
param_event_type: number,
param_window: number | bigint,
param_event_type: number | bigint,
param_element: Deno.PointerValue,
param_event_number: number,
param_bind_id: number,
param_event_number: number | bigint,
param_bind_id: number | bigint,
) => {
// Create elements
const win = param_window;
const event_type = Math.trunc(param_event_type);
const event_type = typeof param_event_type === 'bigint'
? Number(param_event_type)
: Math.trunc(param_event_type);
const element = param_element !== null
? new Deno.UnsafePointerView(param_element).getCString()
: "";
const event_number = Math.trunc(param_event_number);
const bind_id = Math.trunc(param_bind_id);
const event_number = typeof param_event_number === 'bigint'
? Number(param_event_number)
: Math.trunc(param_event_number);
const bind_id = typeof param_bind_id === 'bigint'
? Number(param_bind_id)
: Math.trunc(param_bind_id);

// Set get argument methods
const args = {
Expand All @@ -323,7 +330,7 @@ export class WebUI {
string: (index: number): string => {
return (
new Deno.UnsafePointerView(
this.#lib.symbols.webui_interface_get_string_at(win, event_number, index)
(this.#lib.symbols.webui_interface_get_string_at(win, event_number, index) as Deno.PointerObject<unknown>)
).getCString()
) as string
},
Expand Down Expand Up @@ -351,7 +358,7 @@ export class WebUI {
);
},
);

// Pass the callback pointer to WebUI
this.#lib.symbols.webui_interface_bind(
this.#window,
toCString(id),
Expand Down Expand Up @@ -402,7 +409,7 @@ export class WebUI {
: response;

const lengthView = new Int32Array(
Deno.UnsafePointerView.getArrayBuffer(pointerLength, 4),
Deno.UnsafePointerView.getArrayBuffer((pointerLength as Deno.PointerObject<unknown>), 4),
);
lengthView[0] = buffer.length;

Expand Down

0 comments on commit a29dfb0

Please sign in to comment.