Comparing version 2.2.3 to 2.2.4
@@ -232,11 +232,17 @@ 'use strict'; | ||
async prepareWasm(saxWasm) { | ||
const result = await WebAssembly.instantiate(saxWasm, { | ||
env: { | ||
memoryBase: 0, | ||
tableBase: 0, | ||
memory: new WebAssembly.Memory({ initial: 10 }), | ||
table: new WebAssembly.Table({ initial: 1, element: 'anyfunc' }), | ||
event_listener: this.eventTrap | ||
} | ||
}); | ||
let result; | ||
if (saxWasm instanceof Uint8Array) { | ||
result = await WebAssembly.instantiate(saxWasm, { | ||
env: { | ||
memoryBase: 0, | ||
tableBase: 0, | ||
memory: new WebAssembly.Memory({ initial: 10 }), | ||
table: new WebAssembly.Table({ initial: 1, element: 'anyfunc' }), | ||
event_listener: this.eventTrap | ||
} | ||
}); | ||
} | ||
else { | ||
result = await WebAssembly.instantiateStreaming(saxWasm); | ||
} | ||
if (result && typeof this.events === 'number') { | ||
@@ -243,0 +249,0 @@ const { parser } = this.wasmSaxParser = result.instance.exports; |
@@ -228,11 +228,17 @@ class SaxEventType { | ||
async prepareWasm(saxWasm) { | ||
const result = await WebAssembly.instantiate(saxWasm, { | ||
env: { | ||
memoryBase: 0, | ||
tableBase: 0, | ||
memory: new WebAssembly.Memory({ initial: 10 }), | ||
table: new WebAssembly.Table({ initial: 1, element: 'anyfunc' }), | ||
event_listener: this.eventTrap | ||
} | ||
}); | ||
let result; | ||
if (saxWasm instanceof Uint8Array) { | ||
result = await WebAssembly.instantiate(saxWasm, { | ||
env: { | ||
memoryBase: 0, | ||
tableBase: 0, | ||
memory: new WebAssembly.Memory({ initial: 10 }), | ||
table: new WebAssembly.Table({ initial: 1, element: 'anyfunc' }), | ||
event_listener: this.eventTrap | ||
} | ||
}); | ||
} | ||
else { | ||
result = await WebAssembly.instantiateStreaming(saxWasm); | ||
} | ||
if (result && typeof this.events === 'number') { | ||
@@ -239,0 +245,0 @@ const { parser } = this.wasmSaxParser = result.instance.exports; |
@@ -13,3 +13,3 @@ export declare class SaxEventType { | ||
} | ||
export declare type Detail = Position | Attribute | Text | Tag | ProcInst; | ||
export type Detail = Position | Attribute | Text | Tag | ProcInst; | ||
export declare abstract class Reader<T = Detail> { | ||
@@ -88,3 +88,3 @@ protected data: Uint8Array; | ||
} | ||
declare type TextDecoder = { | ||
type TextDecoder = { | ||
decode: (input?: ArrayBufferView | ArrayBuffer, options?: { | ||
@@ -104,2 +104,3 @@ stream?: boolean; | ||
end(): void; | ||
prepareWasm(source: Response | Promise<Response>): Promise<boolean>; | ||
prepareWasm(saxWasm: Uint8Array): Promise<boolean>; | ||
@@ -106,0 +107,0 @@ eventTrap: (event: number, ptr: number, len: number) => void; |
@@ -13,3 +13,3 @@ export declare class SaxEventType { | ||
} | ||
export declare type Detail = Position | Attribute | Text | Tag | ProcInst; | ||
export type Detail = Position | Attribute | Text | Tag | ProcInst; | ||
export declare abstract class Reader<T = Detail> { | ||
@@ -88,3 +88,3 @@ protected data: Uint8Array; | ||
} | ||
declare type TextDecoder = { | ||
type TextDecoder = { | ||
decode: (input?: ArrayBufferView | ArrayBuffer, options?: { | ||
@@ -104,2 +104,3 @@ stream?: boolean; | ||
end(): void; | ||
prepareWasm(source: Response | Promise<Response>): Promise<boolean>; | ||
prepareWasm(saxWasm: Uint8Array): Promise<boolean>; | ||
@@ -106,0 +107,0 @@ eventTrap: (event: number, ptr: number, len: number) => void; |
@@ -234,11 +234,17 @@ (function (global, factory) { | ||
async prepareWasm(saxWasm) { | ||
const result = await WebAssembly.instantiate(saxWasm, { | ||
env: { | ||
memoryBase: 0, | ||
tableBase: 0, | ||
memory: new WebAssembly.Memory({ initial: 10 }), | ||
table: new WebAssembly.Table({ initial: 1, element: 'anyfunc' }), | ||
event_listener: this.eventTrap | ||
} | ||
}); | ||
let result; | ||
if (saxWasm instanceof Uint8Array) { | ||
result = await WebAssembly.instantiate(saxWasm, { | ||
env: { | ||
memoryBase: 0, | ||
tableBase: 0, | ||
memory: new WebAssembly.Memory({ initial: 10 }), | ||
table: new WebAssembly.Table({ initial: 1, element: 'anyfunc' }), | ||
event_listener: this.eventTrap | ||
} | ||
}); | ||
} | ||
else { | ||
result = await WebAssembly.instantiateStreaming(saxWasm); | ||
} | ||
if (result && typeof this.events === 'number') { | ||
@@ -245,0 +251,0 @@ const { parser } = this.wasmSaxParser = result.instance.exports; |
@@ -13,3 +13,3 @@ export declare class SaxEventType { | ||
} | ||
export declare type Detail = Position | Attribute | Text | Tag | ProcInst; | ||
export type Detail = Position | Attribute | Text | Tag | ProcInst; | ||
export declare abstract class Reader<T = Detail> { | ||
@@ -88,3 +88,3 @@ protected data: Uint8Array; | ||
} | ||
declare type TextDecoder = { | ||
type TextDecoder = { | ||
decode: (input?: ArrayBufferView | ArrayBuffer, options?: { | ||
@@ -104,2 +104,3 @@ stream?: boolean; | ||
end(): void; | ||
prepareWasm(source: Response | Promise<Response>): Promise<boolean>; | ||
prepareWasm(saxWasm: Uint8Array): Promise<boolean>; | ||
@@ -106,0 +107,0 @@ eventTrap: (event: number, ptr: number, len: number) => void; |
{ | ||
"name": "sax-wasm", | ||
"version": "2.2.3", | ||
"version": "2.2.4", | ||
"repository": "https://github.com/justinwilaby/sax-wasm", | ||
@@ -43,4 +43,3 @@ "description": "An extremely fast JSX, HTML and XML parser written in Rust compiled to WebAssembly for Node and the Web", | ||
"libxmljs": "^0.19.7", | ||
"ltx": "^2.9.2", | ||
"node-expat": "^2.4.0", | ||
"ltx": "^3.0.0", | ||
"node-xml": "^1.0.2", | ||
@@ -50,5 +49,5 @@ "rollup": "^2.75.3", | ||
"ts-jest": "^28.0.2", | ||
"ts-node": "9.0.0", | ||
"typescript": "^4.6.4" | ||
"ts-node": "^10.9.1", | ||
"typescript": "^5.1.6" | ||
} | ||
} |
@@ -18,3 +18,3 @@ # SAX (Simple API for XML) for WebAssembly | ||
## Benchmarks (Node v16.14.0 / 2.7 GHz Quad-Core Intel Core i7) | ||
## Benchmarks (Node v18.16.1 / 2.7 GHz Quad-Core Intel Core i7) | ||
All parsers are tested using a large XML document (2.1 MB) containing a variety of elements and is streamed when supported | ||
@@ -29,3 +29,2 @@ by the parser. This attempts to recreate the best real-world use case for parsing XML. Other libraries test benchmarks using a | ||
| [sax-js](https://github.com/isaacs/sax-js) | 155.77 | ☑ | ☑* | | ||
| [node-expat](https://github.com/node-xmpp/node-expat) | 234.78 | ☐ | ☐ | | ||
| [libxmljs](https://github.com/polotek/libxmljs) | 274.95 | ☐ | ☐ | | ||
@@ -73,3 +72,6 @@ | [node-xml](https://github.com/dylang/node-xml) | 685.00 | ☑ | ☐ | | ||
## Usage for the web | ||
1. Instantiate and prepare the wasm for parsing | ||
2. Pipe the document stream to sax-wasm using [ReadableStream.getReader()](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream/getReader) | ||
**NOTE** This uses [WebAssembly.instantiateStreaming](https://developer.mozilla.org/en-US/docs/WebAssembly/JavaScript_interface/instantiateStreaming) | ||
under the hood to load the wasm. | ||
```js | ||
@@ -79,8 +81,6 @@ import { SaxEventType, SAXParser } from 'sax-wasm'; | ||
async function loadAndPrepareWasm() { | ||
const saxWasmResponse = await fetch('./path/to/wasm/sax-wasm.wasm'); | ||
const saxWasmbuffer = await saxWasmResponse.arrayBuffer(); | ||
const parser = new SAXParser(SaxEventType.Attribute | SaxEventType.OpenTag, {highWaterMark: 64 * 1024}); // 64k chunks | ||
// Instantiate and prepare the wasm for parsing | ||
const ready = await parser.prepareWasm(new Uint8Array(saxWasmbuffer)); | ||
const saxWasmResponse = fetch('./path/to/wasm/sax-wasm.wasm'); | ||
const ready = await parser.prepareWasm(saxWasmResponse); | ||
if (ready) { | ||
@@ -145,14 +145,14 @@ return parser; | ||
|Event |Mask |Argument passed to handler | | ||
|----------------------------------|--------------|------------------------------------------------| | ||
|SaxEventType.Text |0b000000000001|text: [Text](src/js/saxWasm.ts#L106) | | ||
|SaxEventType.ProcessingInstruction|0b000000000010|procInst: [Text](src/js/saxWasm.ts#L106) | | ||
|SaxEventType.SGMLDeclaration |0b000000000100|sgmlDecl: [Text](src/js/saxWasm.ts#L106) | | ||
|SaxEventType.Doctype |0b000000001000|doctype: [Text](src/js/saxWasm.ts#L106) | | ||
|SaxEventType.Comment |0b000000010000|comment: [Text](src/js/saxWasm.ts#L106) | | ||
|SaxEventType.OpenTagStart |0b000000100000|tag: [Tag](src/js/saxWasm.ts#L133) | | ||
|SaxEventType.Attribute |0b000001000000|attribute: [Attribute](src/js/saxWasm.ts#L49) | | ||
|SaxEventType.OpenTag |0b000010000000|tag: [Tag](src/js/saxWasm.ts#L133) | | ||
|SaxEventType.CloseTag |0b000100000000|tag: [Tag](src/js/saxWasm.ts#L133) | | ||
|SaxEventType.CDATA |0b001000000000|start: [Position](src/js/saxWasm.ts#L39) | | ||
|Event |Mask | Argument passed to handler | | ||
|----------------------------------|--------------|-----------------------------------------------| | ||
|SaxEventType.Text |0b000000000001| text: [Text](src/js/saxWasm.ts#L114) | | ||
|SaxEventType.ProcessingInstruction|0b000000000010| procInst: [Text](src/js/saxWasm.ts#L114) | | ||
|SaxEventType.SGMLDeclaration |0b000000000100| sgmlDecl: [Text](src/js/saxWasm.ts#L114) | | ||
|SaxEventType.Doctype |0b000000001000| doctype: [Text](src/js/saxWasm.ts#L114) | | ||
|SaxEventType.Comment |0b000000010000| comment: [Text](src/js/saxWasm.ts#L114) | | ||
|SaxEventType.OpenTagStart |0b000000100000| tag: [Tag](src/js/saxWasm.ts#L141) | | ||
|SaxEventType.Attribute |0b000001000000| attribute: [Attribute](src/js/saxWasm.ts#L59) | | ||
|SaxEventType.OpenTag |0b000010000000| tag: [Tag](src/js/saxWasm.ts#L141) | | ||
|SaxEventType.CloseTag |0b000100000000| tag: [Tag](src/js/saxWasm.ts#L141) | | ||
|SaxEventType.CDATA |0b001000000000| start: [Position](src/js/saxWasm.ts#L39) | | ||
@@ -159,0 +159,0 @@ ## Speeding things up on large documents |
90523
19
1238