Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wasm serialize & hook interface #4479

Draft
wants to merge 14 commits into
base: master
Choose a base branch
from
3 changes: 3 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
"addons/xterm-addon-serialize/src/tsconfig.json",
"addons/xterm-addon-serialize/test/tsconfig.json",
"addons/xterm-addon-serialize/benchmark/tsconfig.json",
"addons/xterm-addon-serialize2/src/tsconfig.json",
"addons/xterm-addon-serialize2/test/tsconfig.json",
"addons/xterm-addon-serialize2/benchmark/tsconfig.json",
"addons/xterm-addon-unicode11/src/tsconfig.json",
"addons/xterm-addon-unicode11/test/tsconfig.json",
"addons/xterm-addon-web-links/src/tsconfig.json",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,10 @@ perfContext('Terminal: sh -c "dd if=/dev/urandom count=40 bs=1k | hexdump | lolc
perfContext('serialize', () => {
let terminal: TestTerminal;
const serializeAddon = new SerializeAddon();
before(() => {
before(async () => {
terminal = new TestTerminal({ cols: 80, rows: 25, scrollback: 5000 });
serializeAddon.activate(terminal);
terminal.writeSync(content);
await new Promise<void>(r => terminal.write(content, r));
});
new ThroughputRuntimeCase('', () => {
return { payloadSize: serializeAddon.serialize().length };
Expand Down
10 changes: 10 additions & 0 deletions addons/xterm-addon-serialize2/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
lib
node_modules
out-benchmark

# skip inwasm folders
inwasm-sdks/
inwasm-builds/
!inwasm-builds/**/final.wat
!inwasm-builds/**/final.wasm
!inwasm-builds/**/definition.json
29 changes: 29 additions & 0 deletions addons/xterm-addon-serialize2/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Blacklist - exclude everything except npm defaults such as LICENSE, etc
*
!*/

# Whitelist - lib/
!lib/**/*.d.ts

!lib/**/*.js
!lib/**/*.js.map

!lib/**/*.css

# Whitelist - src/
!src/**/*.ts
!src/**/*.d.ts

!src/**/*.js
!src/**/*.js.map

!src/**/*.css

# Blacklist - src/ test files
src/**/*.test.ts
src/**/*.test.d.ts
src/**/*.test.js
src/**/*.test.js.map

# Whitelist - typings/
!typings/*.d.ts
42 changes: 42 additions & 0 deletions addons/xterm-addon-serialize2/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
## xterm-addon-serialize

An addon for [xterm.js](https://github.com/xtermjs/xterm.js) that enables xterm.js to serialize a terminal framebuffer into string or html. This addon requires xterm.js v4+.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

v4 -> v5.2+? Should we just remove that line as there's the experimental line + we call it out in the release notes?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure thing. I just copy-cloned from the old addon and did not bother to fix all things yet.


⚠️ This is an experimental addon that is still under construction ⚠️

### Install

```bash
npm install --save xterm-addon-serialize
```

### Usage

```ts
import { Terminal } from "xterm";
import { SerializeAddon } from "xterm-addon-serialize";

const terminal = new Terminal();
const serializeAddon = new SerializeAddon();
terminal.loadAddon(serializeAddon);

terminal.write("something...", () => {
console.log(serializeAddon.serialize());
});
```

See the full [API](https://github.com/xtermjs/xterm.js/blob/master/addons/xterm-addon-serialize/typings/xterm-addon-serialize.d.ts) for more advanced usage.

### Benchmark

⚠️ Ensure you have `lolcat`, `hexdump` programs installed in your computer

```shell
$ git clone https://github.com/xtermjs/xterm.js.git
$ cd xterm.js
$ yarn
$ cd addons/xterm-addon-serialize
$ yarn benchmark && yarn benchmark-baseline
$ # change some code in `xterm-addon-serialize`
$ yarn benchmark-eval
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/**
* Copyright (c) 2019 The xterm.js authors. All rights reserved.
* @license MIT
*/

import { perfContext, before, ThroughputRuntimeCase } from 'xterm-benchmark';

import { spawn } from 'node-pty';
import { Utf8ToUtf32, stringFromCodePoint } from 'common/input/TextDecoder';
import { Terminal } from 'browser/public/Terminal';
import { Serialize2Addon } from 'Serialize2Addon';

class TestTerminal extends Terminal {
public writeSync(data: string): void {
(this as any)._core.writeSync(data);
}
}

perfContext('Terminal: sh -c "dd if=/dev/urandom count=40 bs=1k | hexdump | lolcat -f"', () => {
let content = '';
let contentUtf8: Uint8Array;

before(async () => {
const p = spawn('sh', ['-c', 'dd if=/dev/urandom count=40 bs=1k | hexdump | lolcat -f'], {
name: 'xterm-256color',
cols: 80,
rows: 25,
cwd: process.env.HOME,
env: process.env,
encoding: (null as unknown as string) // needs to be fixed in node-pty
});
const chunks: Buffer[] = [];
let length = 0;
p.on('data', data => {
chunks.push(data as unknown as Buffer);
length += data.length;
});
await new Promise<void>(resolve => p.on('exit', () => resolve()));
contentUtf8 = Buffer.concat(chunks, length);
// translate to content string
const buffer = new Uint32Array(contentUtf8.length);
const decoder = new Utf8ToUtf32();
const codepoints = decoder.decode(contentUtf8, buffer);
for (let i = 0; i < codepoints; ++i) {
content += stringFromCodePoint(buffer[i]);
// peek into content to force flat repr in v8
if (!(i % 10000000)) {
content[i];
}
}
});

perfContext('serialize', () => {
let terminal: TestTerminal;
const serializeAddon = new Serialize2Addon();
before(async () => {
terminal = new TestTerminal({ cols: 80, rows: 25, scrollback: 5000 });
serializeAddon.activate(terminal);
await new Promise<void>(r => terminal.write(content, r));
});
new ThroughputRuntimeCase('', () => {
return { payloadSize: serializeAddon.serialize().length };
}, { fork: false }).showAverageThroughput();
});
});
19 changes: 19 additions & 0 deletions addons/xterm-addon-serialize2/benchmark/benchmark.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"APP_PATH": ".benchmark",
"evalConfig": {
"tolerance": {
"*": [0.75, 1.5],
"*.dev": [0.01, 1.5],
"*.cv": [0.01, 1.5],
"EscapeSequenceParser.benchmark.js.*.averageThroughput.mean": [0.9, 5]
},
"skip": [
"*.median",
"*.runs",
"*.dev",
"*.cv",
"EscapeSequenceParser.benchmark.js.*.averageRuntime",
"Terminal.benchmark.js.*.averageRuntime"
]
}
}
23 changes: 23 additions & 0 deletions addons/xterm-addon-serialize2/benchmark/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"compilerOptions": {
"lib": ["dom", "es6"],
"outDir": "../out-benchmark",
"types": ["../../../node_modules/@types/node"],
"moduleResolution": "node",
"strict": false,
"target": "es2015",
"module": "commonjs",
"baseUrl": ".",
"paths": {
"common/*": ["../../../src/common/*"],
"browser/*": ["../../../src/browser/*"],
"Serialize2Addon": ["../src/Serialize2Addon"]
}
},
"include": ["../**/*", "../../../typings/xterm.d.ts"],
"exclude": ["../../../**/*test.ts", "../../**/*api.ts"],
"references": [
{ "path": "../../../src/common" },
{ "path": "../../../src/browser" }
]
}
Binary file not shown.
32 changes: 32 additions & 0 deletions addons/xterm-addon-serialize2/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"name": "xterm-addon-serialize2",
"version": "0.1.0",
"author": {
"name": "The xterm.js authors",
"url": "https://xtermjs.org/"
},
"main": "lib/xterm-addon-serialize2.js",
"types": "typings/xterm-addon-serialize2.d.ts",
"repository": "https://github.com/xtermjs/xterm.js",
"license": "MIT",
"keywords": [
"terminal",
"xterm",
"xterm.js"
],
"scripts": {
"inwasm": "inwasm out/*.wasm.js",
"prepackage": "../../node_modules/.bin/tsc -p . && inwasm -f out/*.wasm.js",
"package": "../../node_modules/.bin/webpack",
"prepublishOnly": "npm run package",
"benchmark": "NODE_PATH=../../out:./out:./out-benchmark/ ../../node_modules/.bin/xterm-benchmark -r 5 -c benchmark/benchmark.json",
"benchmark-baseline": "NODE_PATH=../../out:./out:./out-benchmark/ ../../node_modules/.bin/xterm-benchmark -r 5 -c benchmark/benchmark.json --baseline out-benchmark/benchmark/*benchmark.js",
"benchmark-eval": "NODE_PATH=../../out:./out:./out-benchmark/ ../../node_modules/.bin/xterm-benchmark -r 5 -c benchmark/benchmark.json --eval out-benchmark/benchmark/*benchmark.js"
},
"peerDependencies": {
"xterm": "^5.0.0"
},
"devDependencies": {
"inwasm": "^0.0.13"
}
}
Loading