mirror of
https://codeberg.org/demostf/inspector.git
synced 2026-06-03 18:14:08 +02:00
split out worker stuff
This commit is contained in:
parent
d360ffec68
commit
a1838c5164
5 changed files with 294 additions and 218 deletions
184
www/src/App.tsx
Normal file
184
www/src/App.tsx
Normal file
|
|
@ -0,0 +1,184 @@
|
||||||
|
import {Packet} from "./parser";
|
||||||
|
import React, {useCallback, Component} from 'react'
|
||||||
|
import {useDropzone} from 'react-dropzone'
|
||||||
|
import {Header} from "./header";
|
||||||
|
import {PacketDetails, PacketTable} from "./table";
|
||||||
|
import {isSearchEmpty, SearchBar, SearchFilter} from "./search";
|
||||||
|
import {DemoWorker, ResponseMessageData} from "./rpc";
|
||||||
|
|
||||||
|
let _style = require('../styles/style.css');
|
||||||
|
|
||||||
|
export interface PacketMeta {
|
||||||
|
index: number,
|
||||||
|
tick: number,
|
||||||
|
ty: PacketType,
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum PacketType {
|
||||||
|
Signon = 1,
|
||||||
|
Message = 2,
|
||||||
|
SyncTick = 3,
|
||||||
|
ConsoleCmd = 4,
|
||||||
|
UserCmd = 5,
|
||||||
|
DataTables = 6,
|
||||||
|
Stop = 7,
|
||||||
|
StringTables = 8,
|
||||||
|
}
|
||||||
|
|
||||||
|
interface AppState {
|
||||||
|
loading: boolean,
|
||||||
|
header: Header | null,
|
||||||
|
progress: number,
|
||||||
|
packets: PacketMeta[],
|
||||||
|
prop_names: Map<string, { table: string, prop: string }>,
|
||||||
|
class_names: Map<number, string>,
|
||||||
|
active: Packet | null,
|
||||||
|
activeIndex: number | null,
|
||||||
|
search: SearchFilter,
|
||||||
|
matches: number[],
|
||||||
|
worker: DemoWorker | null,
|
||||||
|
}
|
||||||
|
|
||||||
|
export class App extends Component<{}, AppState> {
|
||||||
|
state: AppState = {
|
||||||
|
loading: false,
|
||||||
|
header: null,
|
||||||
|
progress: 0,
|
||||||
|
packets: [],
|
||||||
|
prop_names: new Map(),
|
||||||
|
class_names: new Map(),
|
||||||
|
active: null,
|
||||||
|
activeIndex: null,
|
||||||
|
search: {
|
||||||
|
entity: 0,
|
||||||
|
search: "",
|
||||||
|
class_ids: [],
|
||||||
|
prop_ids: [],
|
||||||
|
},
|
||||||
|
matches: [],
|
||||||
|
worker: null
|
||||||
|
}
|
||||||
|
|
||||||
|
onSearch = debounce((search: SearchFilter) => {
|
||||||
|
if (!isSearchEmpty(search) && this.state.worker) {
|
||||||
|
console.log(search);
|
||||||
|
this.state.worker.search(search).then(matches => this.setState({matches}));
|
||||||
|
}
|
||||||
|
this.setState({search});
|
||||||
|
}, 500)
|
||||||
|
|
||||||
|
selectPacket = (packet: number) => {
|
||||||
|
this.state.worker.get(packet).then(packet => this.setState({active: packet}));
|
||||||
|
}
|
||||||
|
|
||||||
|
async load(data: ArrayBuffer) {
|
||||||
|
this.setState({loading: true});
|
||||||
|
const worker = new DemoWorker();
|
||||||
|
this.setState({worker});
|
||||||
|
const parsed = await worker.load(data, (progress) => {
|
||||||
|
this.setState({progress});
|
||||||
|
});
|
||||||
|
|
||||||
|
const prop_names = new Map();
|
||||||
|
for (let prop of parsed.prop_names) {
|
||||||
|
prop_names.set(prop.identifier, prop);
|
||||||
|
}
|
||||||
|
const class_names = new Map();
|
||||||
|
for (let c of parsed.class_names) {
|
||||||
|
class_names.set(c.identifier, c.name);
|
||||||
|
}
|
||||||
|
this.setState({
|
||||||
|
loading: false,
|
||||||
|
packets: parsed.packets,
|
||||||
|
header: parsed.header,
|
||||||
|
prop_names,
|
||||||
|
class_names
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
filteredPackets(): PacketMeta[] {
|
||||||
|
if (isSearchEmpty(this.state.search)) {
|
||||||
|
return this.state.packets;
|
||||||
|
} else {
|
||||||
|
return this.state.matches.map(index => this.state.packets[index]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
if (this.state.loading && this.state.progress > 0) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<h1>Loading</h1>
|
||||||
|
<progress value={this.state.progress} max={100}/>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
} else if (this.state.loading) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<h1>Loading</h1>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
} else if (this.state.packets.length) {
|
||||||
|
let active = <></>;
|
||||||
|
const packets = this.filteredPackets();
|
||||||
|
if (this.state.active) {
|
||||||
|
active = <div className="details"><PacketDetails packet={this.state.active}
|
||||||
|
search={this.state.search}
|
||||||
|
prop_names={this.state.prop_names}
|
||||||
|
class_names={this.state.class_names}/></div>
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<SearchBar onSearch={this.onSearch} class_names={this.state.class_names}
|
||||||
|
prop_names={this.state.prop_names}/>
|
||||||
|
<div className="packets">
|
||||||
|
<PacketTable packets={packets} class_names={this.state.class_names}
|
||||||
|
activeIndex={this.state.activeIndex}
|
||||||
|
prop_names={this.state.prop_names}
|
||||||
|
onClick={this.selectPacket}/>
|
||||||
|
{active}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<DemoDropzone onDrop={(data) => this.load(data)}/>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function DemoDropzone({onDrop}: { onDrop: (data: ArrayBuffer) => void }) {
|
||||||
|
const onDropCb = useCallback((acceptedFiles: File[]) => {
|
||||||
|
let reader = new FileReader();
|
||||||
|
reader.readAsArrayBuffer(acceptedFiles[0]);
|
||||||
|
reader.addEventListener('load', () => {
|
||||||
|
let result = reader.result as ArrayBuffer;
|
||||||
|
onDrop(result)
|
||||||
|
});
|
||||||
|
}, [])
|
||||||
|
const {getRootProps, getInputProps, isDragActive} = useDropzone({onDrop: onDropCb})
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="dropzone" {...getRootProps()}>
|
||||||
|
<input {...getInputProps()} />
|
||||||
|
{
|
||||||
|
isDragActive ?
|
||||||
|
<p>Drop the demo file here ...</p> :
|
||||||
|
<p>Drag 'n' drop a demo here, or click to select a file</p>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function debounce(func: Function, timeout = 300) {
|
||||||
|
let timer: any;
|
||||||
|
return (...args: any[]) => {
|
||||||
|
clearTimeout(timer);
|
||||||
|
timer = setTimeout(() => {
|
||||||
|
func.apply(this, args);
|
||||||
|
}, timeout);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -1,208 +1,7 @@
|
||||||
import {Packet} from "./parser";
|
import React from 'react'
|
||||||
import React, {useCallback, Component} from 'react'
|
import {createRoot} from "react-dom/client";
|
||||||
import {useDropzone} from 'react-dropzone'
|
import {App} from './App'
|
||||||
import ReactDOM from "react-dom";
|
|
||||||
import { createRoot } from 'react-dom/client';
|
|
||||||
import {Header} from "./header";
|
|
||||||
import {PacketDetails, PacketTable} from "./table";
|
|
||||||
import {filterPacket, isSearchEmpty, SearchBar, SearchFilter} from "./search";
|
|
||||||
import {ResponseMessageData} from "./rpc";
|
|
||||||
|
|
||||||
let _style = require('../styles/style.css');
|
|
||||||
|
|
||||||
export interface PacketMeta {
|
|
||||||
index: number,
|
|
||||||
tick: number,
|
|
||||||
ty: PacketType,
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum PacketType {
|
|
||||||
Signon = 1,
|
|
||||||
Message = 2,
|
|
||||||
SyncTick = 3,
|
|
||||||
ConsoleCmd = 4,
|
|
||||||
UserCmd = 5,
|
|
||||||
DataTables = 6,
|
|
||||||
Stop = 7,
|
|
||||||
StringTables = 8,
|
|
||||||
}
|
|
||||||
|
|
||||||
interface AppState {
|
|
||||||
loading: boolean,
|
|
||||||
header: Header | null,
|
|
||||||
progress: number,
|
|
||||||
packets: PacketMeta[],
|
|
||||||
prop_names: Map<string, { table: string, prop: string }>,
|
|
||||||
class_names: Map<number, string>,
|
|
||||||
active: Packet | null,
|
|
||||||
activeIndex: number | null,
|
|
||||||
search: SearchFilter,
|
|
||||||
matches: number[],
|
|
||||||
worker: Worker
|
|
||||||
}
|
|
||||||
|
|
||||||
class App extends Component<{}, AppState> {
|
|
||||||
state: AppState = {
|
|
||||||
loading: false,
|
|
||||||
header: null,
|
|
||||||
progress: 0,
|
|
||||||
packets: [],
|
|
||||||
prop_names: new Map(),
|
|
||||||
class_names: new Map(),
|
|
||||||
active: null,
|
|
||||||
activeIndex: null,
|
|
||||||
search: {
|
|
||||||
entity: 0,
|
|
||||||
search: "",
|
|
||||||
class_ids: [],
|
|
||||||
prop_ids: [],
|
|
||||||
},
|
|
||||||
matches: [],
|
|
||||||
worker: null
|
|
||||||
}
|
|
||||||
|
|
||||||
onSearch = debounce((search: SearchFilter) => {
|
|
||||||
if (!isSearchEmpty(search)) {
|
|
||||||
console.log(search);
|
|
||||||
this.state.worker.postMessage({type: "search", filter: search});
|
|
||||||
}
|
|
||||||
this.setState({search});
|
|
||||||
}, 500)
|
|
||||||
|
|
||||||
load(data: ArrayBuffer) {
|
|
||||||
this.setState({loading: true});
|
|
||||||
const worker = new Worker('./worker.js');
|
|
||||||
this.setState({worker});
|
|
||||||
worker.addEventListener("message", (event: MessageEvent<ResponseMessageData>) => {
|
|
||||||
const data = event.data;
|
|
||||||
if (data.type !== "progress") {
|
|
||||||
console.log(data);
|
|
||||||
}
|
|
||||||
switch (data.type) {
|
|
||||||
case "progress":
|
|
||||||
let progress = data.progress;
|
|
||||||
this.setState({progress});
|
|
||||||
break;
|
|
||||||
case "done":
|
|
||||||
const prop_names = new Map();
|
|
||||||
for (let prop of data.prop_names) {
|
|
||||||
prop_names.set(prop.identifier, prop);
|
|
||||||
}
|
|
||||||
const class_names = new Map();
|
|
||||||
for (let c of data.class_names) {
|
|
||||||
class_names.set(c.identifier, c.name);
|
|
||||||
}
|
|
||||||
this.setState({
|
|
||||||
loading: false,
|
|
||||||
packets: data.packets,
|
|
||||||
header: data.header,
|
|
||||||
prop_names,
|
|
||||||
class_names
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case "packet":
|
|
||||||
this.setState({active: data.packet});
|
|
||||||
break;
|
|
||||||
case "search_result":
|
|
||||||
this.setState({matches: data.matches});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
worker.postMessage({
|
|
||||||
type: "data",
|
|
||||||
data
|
|
||||||
}, [data]);
|
|
||||||
}
|
|
||||||
|
|
||||||
filteredPackets(): PacketMeta[] {
|
|
||||||
if (isSearchEmpty(this.state.search)) {
|
|
||||||
return this.state.packets;
|
|
||||||
} else {
|
|
||||||
return this.state.matches.map(index => this.state.packets[index]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
if (this.state.loading && this.state.progress > 0) {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<h1>Loading</h1>
|
|
||||||
<progress value={this.state.progress} max={100}/>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
} else if (this.state.loading) {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<h1>Loading</h1>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
} else if (this.state.packets.length) {
|
|
||||||
let active = <></>;
|
|
||||||
const packets = this.filteredPackets();
|
|
||||||
if (this.state.active) {
|
|
||||||
active = <div className="details"><PacketDetails packet={this.state.active}
|
|
||||||
search={this.state.search}
|
|
||||||
prop_names={this.state.prop_names}
|
|
||||||
class_names={this.state.class_names}/></div>
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<SearchBar onSearch={this.onSearch} class_names={this.state.class_names}
|
|
||||||
prop_names={this.state.prop_names}/>
|
|
||||||
<div className="packets">
|
|
||||||
<PacketTable packets={packets} class_names={this.state.class_names}
|
|
||||||
activeIndex={this.state.activeIndex}
|
|
||||||
prop_names={this.state.prop_names}
|
|
||||||
onClick={(index) => {
|
|
||||||
this.state.worker.postMessage({type: "get", packet: index})
|
|
||||||
}}/>
|
|
||||||
{active}
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<DemoDropzone onDrop={(data) => this.load(data)}/>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const container = document.getElementById('root');
|
const container = document.getElementById('root');
|
||||||
const root = createRoot(container);
|
const root = createRoot(container);
|
||||||
root.render(<App/>);
|
root.render(<App/>);
|
||||||
|
|
||||||
function DemoDropzone({onDrop}: { onDrop: (data: ArrayBuffer) => void }) {
|
|
||||||
const onDropCb = useCallback((acceptedFiles: File[]) => {
|
|
||||||
let reader = new FileReader();
|
|
||||||
reader.readAsArrayBuffer(acceptedFiles[0]);
|
|
||||||
reader.addEventListener('load', () => {
|
|
||||||
let result = reader.result as ArrayBuffer;
|
|
||||||
onDrop(result)
|
|
||||||
});
|
|
||||||
}, [])
|
|
||||||
const {getRootProps, getInputProps, isDragActive} = useDropzone({onDrop: onDropCb})
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="dropzone" {...getRootProps()}>
|
|
||||||
<input {...getInputProps()} />
|
|
||||||
{
|
|
||||||
isDragActive ?
|
|
||||||
<p>Drop the demo file here ...</p> :
|
|
||||||
<p>Drag 'n' drop a demo here, or click to a file</p>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function debounce(func: Function, timeout = 300) {
|
|
||||||
let timer: any;
|
|
||||||
return (...args: any[]) => {
|
|
||||||
clearTimeout(timer);
|
|
||||||
timer = setTimeout(() => {
|
|
||||||
func.apply(this, args);
|
|
||||||
}, timeout);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
109
www/src/rpc.ts
109
www/src/rpc.ts
|
|
@ -1,14 +1,105 @@
|
||||||
import {SearchFilter} from "./search";
|
import {SearchFilter} from "./search";
|
||||||
import {Packet} from "./parser";
|
import {Packet} from "./parser";
|
||||||
import {Header} from "./header";
|
import {Header} from "./header";
|
||||||
import {PacketMeta} from "./index";
|
import {PacketMeta} from "./App";
|
||||||
|
import {Simulate} from "react-dom/test-utils";
|
||||||
|
import progress = Simulate.progress;
|
||||||
|
|
||||||
export type RequestMessageData = {type: "data", data: ArrayBuffer}
|
export type RequestMessageData = { type: "data", sequence?: number, data: ArrayBuffer }
|
||||||
| {type: "get", packet: number}
|
| { type: "get", sequence?: number, packet: number }
|
||||||
| {type: "search", filter: SearchFilter}
|
| { type: "search", sequence?: number, filter: SearchFilter }
|
||||||
|
|
||||||
export type ResponseMessageData = { type: "progress", progress: number }
|
export type ResponseMessageData = { type: "error", sequence: number, e: Error }
|
||||||
| { type: "packet", packet: Packet }
|
|{ type: "progress", sequence: number, progress: number }
|
||||||
| { type: "done", packets: PacketMeta[], header: Header, prop_names: { identifier: string, table: string, prop: string }[], class_names: { identifier: number, name: string }[] }
|
| { type: "packet", sequence: number, packet: Packet }
|
||||||
| { type: "packet_names", packet: {} }
|
| { type: "done", sequence: number, packets: PacketMeta[], header: Header, prop_names: { identifier: string, table: string, prop: string }[], class_names: { identifier: number, name: string }[] }
|
||||||
| { type: "search_result", matches: number[] };
|
| { type: "search_result", sequence: number, matches: number[] };
|
||||||
|
|
||||||
|
const ResponseTypeMap = {
|
||||||
|
"search": "search_result",
|
||||||
|
"get": "packet",
|
||||||
|
"data": "done",
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ParsedDemo {
|
||||||
|
packets: PacketMeta[],
|
||||||
|
header: Header,
|
||||||
|
prop_names: { identifier: string, table: string, prop: string }[],
|
||||||
|
class_names: { identifier: number, name: string }[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export class DemoWorker {
|
||||||
|
worker: Worker
|
||||||
|
packets: PacketMeta[] = [];
|
||||||
|
lastSequence = 0;
|
||||||
|
callbacks: Map<number, [(_: ResponseMessageData) => void, (_: Error) => void]>;
|
||||||
|
onProgress: null | ((progress: number) => void) = null;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.callbacks = new Map();
|
||||||
|
this.worker = new Worker('./worker.js');
|
||||||
|
this.worker.addEventListener("message", (event: MessageEvent<ResponseMessageData>) => {
|
||||||
|
const data = event.data;
|
||||||
|
const sequence = data.sequence;
|
||||||
|
const [resolve, reject] = this.callbacks.get(sequence);
|
||||||
|
if (data.type == "error") {
|
||||||
|
this.callbacks.delete(sequence);
|
||||||
|
reject(data.e);
|
||||||
|
} else if (data.type === "progress") {
|
||||||
|
if (this.onProgress) {
|
||||||
|
this.onProgress(data.progress);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.callbacks.delete(sequence);
|
||||||
|
resolve(event.data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
postMessage(message: RequestMessageData, transfer: Transferable[] = []): Promise<ResponseMessageData> {
|
||||||
|
const sequence = this.lastSequence++;
|
||||||
|
message.sequence = sequence;
|
||||||
|
this.worker.postMessage(message, transfer);
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
this.callbacks.set(sequence, [resolve, reject]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public async load(data: ArrayBuffer, onProgress: (progress: number) => void): Promise<ParsedDemo> {
|
||||||
|
this.onProgress = onProgress;
|
||||||
|
const response = await this.postMessage({
|
||||||
|
type: "data",
|
||||||
|
data,
|
||||||
|
}, [data]);
|
||||||
|
this.onProgress = null;
|
||||||
|
if (response.type === "done") {
|
||||||
|
return response;
|
||||||
|
} else {
|
||||||
|
throw new Error("Invalid response type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async get(packet: number): Promise<Packet> {
|
||||||
|
const response = await this.postMessage({
|
||||||
|
type: "get",
|
||||||
|
packet,
|
||||||
|
});
|
||||||
|
if (response.type === "packet") {
|
||||||
|
return response.packet;
|
||||||
|
} else {
|
||||||
|
throw new Error("Invalid response type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async search(filter: SearchFilter): Promise<number[]> {
|
||||||
|
const response = await this.postMessage({
|
||||||
|
type: "search",
|
||||||
|
filter,
|
||||||
|
});
|
||||||
|
if (response.type === "search_result") {
|
||||||
|
return response.matches;
|
||||||
|
} else {
|
||||||
|
throw new Error("Invalid response type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4,7 +4,7 @@ import {FixedSizeList as List} from 'react-window';
|
||||||
import {MessageInfo} from "./packets/message";
|
import {MessageInfo} from "./packets/message";
|
||||||
import {UserCmdDetails} from "./packets/usercmd";
|
import {UserCmdDetails} from "./packets/usercmd";
|
||||||
import {filterMessage, filterPacket, SearchFilter} from "./search";
|
import {filterMessage, filterPacket, SearchFilter} from "./search";
|
||||||
import {PacketMeta, PacketType} from "./index"
|
import {PacketMeta, PacketType} from "./App"
|
||||||
|
|
||||||
interface TableProps {
|
interface TableProps {
|
||||||
packets: PacketMeta[],
|
packets: PacketMeta[],
|
||||||
|
|
|
||||||
|
|
@ -7,32 +7,34 @@ let parser: Parser | null = null;
|
||||||
|
|
||||||
onmessage = function (event: MessageEvent<RequestMessageData>) {
|
onmessage = function (event: MessageEvent<RequestMessageData>) {
|
||||||
const data = event.data;
|
const data = event.data;
|
||||||
|
const sequence = data.sequence;
|
||||||
switch (data.type) {
|
switch (data.type) {
|
||||||
case "data":
|
case "data":
|
||||||
import("demo-inspector")
|
import("demo-inspector")
|
||||||
.then(({Parser}) => {
|
.then(({Parser}) => {
|
||||||
parser = new Parser(new Uint8Array(data.data), (progress: number) => {
|
parser = new Parser(new Uint8Array(data.data), (progress: number) => {
|
||||||
postMessage({type: "progress", progress})
|
postMessage({type: "progress", progress, sequence})
|
||||||
});
|
});
|
||||||
postMessage({
|
postMessage({
|
||||||
type: "done",
|
type: "done",
|
||||||
packets: parser.packets(),
|
packets: parser.packets(),
|
||||||
header: parser.header(),
|
header: parser.header(),
|
||||||
prop_names: parser.prop_names(),
|
prop_names: parser.prop_names(),
|
||||||
class_names: parser.class_names()
|
class_names: parser.class_names(),
|
||||||
|
sequence
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
break;
|
break;
|
||||||
case "search":
|
case "search":
|
||||||
if (parser) {
|
if (parser) {
|
||||||
const matches = parser.search(data.filter);
|
const matches = parser.search(data.filter);
|
||||||
postMessage({type: "search_result", matches: Array.prototype.slice.call(matches)})
|
postMessage({type: "search_result", matches: Array.prototype.slice.call(matches), sequence})
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "get":
|
case "get":
|
||||||
if (parser) {
|
if (parser) {
|
||||||
const packet = parser.packet(data.packet);
|
const packet = parser.packet(data.packet);
|
||||||
postMessage({type: "packet", packet})
|
postMessage({type: "packet", packet, sequence})
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue