js-dos 8.1.4 → 8.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/emulators/emulators.js +2 -0
- package/dist/emulators/emulators.js.map +1 -0
- package/dist/emulators/types/build.d.ts +28 -0
- package/dist/emulators/types/dos/bundle/dos-bundle.d.ts +20 -0
- package/dist/emulators/types/dos/dosbox/ts/direct.d.ts +3 -0
- package/dist/emulators/types/dos/dosbox/ts/worker.d.ts +3 -0
- package/dist/emulators/types/emulators.d.ts +76 -0
- package/dist/emulators/types/http.d.ts +9 -0
- package/dist/emulators/types/impl/ci-impl.d.ts +29 -0
- package/dist/emulators/types/impl/emulators-impl.d.ts +26 -0
- package/dist/emulators/types/impl/modules.d.ts +38 -0
- package/dist/emulators/types/libzip/libzip.d.ts +16 -0
- package/dist/emulators/types/protocol/messages-queue.d.ts +8 -0
- package/dist/emulators/types/protocol/protocol.d.ts +128 -0
- package/dist/emulators/wdosbox-x.js +55 -0
- package/dist/emulators/wdosbox-x.js.symbols +8760 -0
- package/dist/emulators/wdosbox-x.wasm +0 -0
- package/dist/emulators/wdosbox.js +55 -0
- package/dist/emulators/wdosbox.js.symbols +3001 -0
- package/dist/emulators/wdosbox.wasm +0 -0
- package/dist/emulators/wlibzip.js +21 -0
- package/dist/emulators/wlibzip.js.symbols +268 -0
- package/dist/emulators/wlibzip.wasm +0 -0
- package/dist/js-dos.css +1 -0
- package/dist/js-dos.js +22 -0
- package/dist/js-dos.js.map +1 -0
- package/package.json +1 -1
- package/release.zip +0 -0
- package/.eslintrc.json +0 -43
- package/.github/workflows/build.yml +0 -51
- package/.gitmodules +0 -4
- package/index.html +0 -110
- package/postcss.config.cjs +0 -8
- package/src/app.css +0 -14
- package/src/base.css +0 -10
- package/src/components/checkbox.tsx +0 -41
- package/src/components/close-button.tsx +0 -17
- package/src/components/components.css +0 -28
- package/src/components/dos-option-checkbox.tsx +0 -94
- package/src/components/dos-option-select.tsx +0 -108
- package/src/components/dos-option-slider.tsx +0 -35
- package/src/components/error.tsx +0 -16
- package/src/components/loading.tsx +0 -26
- package/src/components/lock.tsx +0 -10
- package/src/components/select.tsx +0 -33
- package/src/components/slider.tsx +0 -69
- package/src/download-file.ts +0 -18
- package/src/frame/account-frame.tsx +0 -156
- package/src/frame/editor/defaults.ts +0 -419
- package/src/frame/editor/editor-conf-frame.tsx +0 -227
- package/src/frame/editor/editor-frame.css +0 -55
- package/src/frame/editor/editor-fs-frame.tsx +0 -314
- package/src/frame/fat-drives-frame.tsx +0 -199
- package/src/frame/frame.css +0 -119
- package/src/frame/frame.tsx +0 -34
- package/src/frame/image-rendering-frame.tsx +0 -8
- package/src/frame/network-frame.tsx +0 -157
- package/src/frame/quick-save-frame.tsx +0 -98
- package/src/frame/settings-frame.tsx +0 -14
- package/src/frame/stats-frame.tsx +0 -87
- package/src/host/bundle-storage.ts +0 -91
- package/src/host/fullscreen.ts +0 -35
- package/src/host/lcache.ts +0 -203
- package/src/host/lstorage.ts +0 -156
- package/src/i18n.ts +0 -185
- package/src/index.css +0 -7
- package/src/load.ts +0 -132
- package/src/login/login.css +0 -9
- package/src/login/login.tsx +0 -77
- package/src/main.tsx +0 -197
- package/src/public/types.ts +0 -45
- package/src/sidebar/account-button.tsx +0 -33
- package/src/sidebar/cloud-save-button.tsx +0 -89
- package/src/sidebar/diskette-icon.tsx +0 -14
- package/src/sidebar/fullscreen-button.tsx +0 -44
- package/src/sidebar/network-button.tsx +0 -39
- package/src/sidebar/sidebar-button.tsx +0 -244
- package/src/sidebar/sidebar.css +0 -47
- package/src/sidebar/sidebar.tsx +0 -30
- package/src/sockdrive/LICENSE +0 -674
- package/src/sockdrive/README.md +0 -45
- package/src/sockdrive/include/sockdrive.h +0 -23
- package/src/sockdrive/js/.eslintrc.json +0 -43
- package/src/sockdrive/js/package.json +0 -29
- package/src/sockdrive/js/src/fatfs/chains.js +0 -318
- package/src/sockdrive/js/src/fatfs/dir.js +0 -385
- package/src/sockdrive/js/src/fatfs/helpers.js +0 -210
- package/src/sockdrive/js/src/fatfs/index.js +0 -606
- package/src/sockdrive/js/src/fatfs/structs.js +0 -255
- package/src/sockdrive/js/src/fatfs/vol.js +0 -166
- package/src/sockdrive/js/src/sockdrive/cache.ts +0 -56
- package/src/sockdrive/js/src/sockdrive/drive.ts +0 -471
- package/src/sockdrive/js/src/sockdrive/lru.ts +0 -221
- package/src/sockdrive/js/src/sockdrive/types.ts +0 -14
- package/src/sockdrive/js/src/sockdrive-fat.d.ts +0 -64
- package/src/sockdrive/js/src/sockdrive-fat.ts +0 -226
- package/src/sockdrive/js/src/sockdrive-native.ts +0 -100
- package/src/sockdrive/js/src/test/test.ts +0 -289
- package/src/sockdrive/js/tsconfig.json +0 -11
- package/src/sockdrive/js/webpack.config.js +0 -68
- package/src/sockdrive/js/yarn.lock +0 -1808
- package/src/store/auth.ts +0 -115
- package/src/store/dos.ts +0 -305
- package/src/store/editor.ts +0 -61
- package/src/store/init.ts +0 -48
- package/src/store/storage.ts +0 -32
- package/src/store/ui.ts +0 -191
- package/src/store.tsx +0 -116
- package/src/ui.tsx +0 -140
- package/src/v8/changes.ts +0 -56
- package/src/v8/config.ts +0 -20
- package/src/v8/subscriptions.ts +0 -62
- package/src/vite-env.d.ts +0 -5
- package/src/window/dos/controls/keyboard.ts +0 -32
- package/src/window/dos/controls/keys.ts +0 -331
- package/src/window/dos/controls/mouse/mount.ts +0 -99
- package/src/window/dos/controls/mouse/mouse-locked.ts +0 -51
- package/src/window/dos/controls/mouse/mouse-not-locked.ts +0 -84
- package/src/window/dos/controls/mouse/mouse-swipe.ts +0 -57
- package/src/window/dos/controls/mouse/pointer.ts +0 -85
- package/src/window/dos/controls/mouse.ts +0 -21
- package/src/window/dos/dos-dhry2.tsx +0 -191
- package/src/window/dos/dos-runtime.tsx +0 -216
- package/src/window/dos/dos-window.tsx +0 -91
- package/src/window/dos/render/canvas.ts +0 -65
- package/src/window/dos/render/resize.ts +0 -31
- package/src/window/dos/render/webgl.ts +0 -173
- package/src/window/dos/sound/audio-node.ts +0 -148
- package/src/window/error-window.tsx +0 -9
- package/src/window/loading-window.tsx +0 -54
- package/src/window/prerun-window.tsx +0 -121
- package/src/window/select-window.tsx +0 -118
- package/src/window/window.css +0 -78
- package/src/window/window.tsx +0 -49
- package/src/ws/ws-sockdrive.ts +0 -123
- package/src/ws/ws-transport-layer.ts +0 -468
- package/tailwind.config.cjs +0 -48
- package/tsconfig.json +0 -32
- package/tsconfig.node.json +0 -9
- package/vite.config.ts +0 -25
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
interface Stats {
|
|
2
|
-
read: number,
|
|
3
|
-
write: number,
|
|
4
|
-
readTotalTime: number,
|
|
5
|
-
cacheHit: number,
|
|
6
|
-
cacheMiss: number,
|
|
7
|
-
cacheUsed: number,
|
|
8
|
-
}
|
|
9
|
-
interface StatsBase<T> {
|
|
10
|
-
isFile(): boolean;
|
|
11
|
-
isDirectory(): boolean;
|
|
12
|
-
isBlockDevice(): boolean;
|
|
13
|
-
isCharacterDevice(): boolean;
|
|
14
|
-
isSymbolicLink(): boolean;
|
|
15
|
-
isFIFO(): boolean;
|
|
16
|
-
isSocket(): boolean;
|
|
17
|
-
dev: T;
|
|
18
|
-
ino: T;
|
|
19
|
-
mode: T;
|
|
20
|
-
nlink: T;
|
|
21
|
-
uid: T;
|
|
22
|
-
gid: T;
|
|
23
|
-
rdev: T;
|
|
24
|
-
size: T;
|
|
25
|
-
blksize: T;
|
|
26
|
-
blocks: T;
|
|
27
|
-
atimeMs: T;
|
|
28
|
-
mtimeMs: T;
|
|
29
|
-
ctimeMs: T;
|
|
30
|
-
birthtimeMs: T;
|
|
31
|
-
atime: Date;
|
|
32
|
-
mtime: Date;
|
|
33
|
-
ctime: Date;
|
|
34
|
-
birthtime: Date;
|
|
35
|
-
}
|
|
36
|
-
interface Stats extends StatsBase<number> { }
|
|
37
|
-
type FileDescriptor = number;
|
|
38
|
-
export interface SockdriveInstance {
|
|
39
|
-
stats: Stats,
|
|
40
|
-
fs: {
|
|
41
|
-
mkdir: (path: string) => Promise<void>,
|
|
42
|
-
readdir: (path: string) => Promise<string[]>,
|
|
43
|
-
fopen: (path: string, flags: string | number, mode: number) => Promise<FileDescriptor>,
|
|
44
|
-
fread: (fd: FileDescriptor, buf: Uint8Array, offset: number,
|
|
45
|
-
length: number, pos: number | null) => Promise<number>,
|
|
46
|
-
fwrite: (fd: FileDescriptor, buf: Uint8Array, offset: number,
|
|
47
|
-
length: number, pos: number | null) => Promise<number>,
|
|
48
|
-
fstat: (fd: FileDescriptor) => Promise<Stats>,
|
|
49
|
-
fclose: (fd: FileDescriptor) => Promise<void>,
|
|
50
|
-
stat: (path: string) => Promise<Stats>,
|
|
51
|
-
isdir: (path: string) => Promise<boolean>,
|
|
52
|
-
exists: (path: string) => Promise<boolean>,
|
|
53
|
-
}
|
|
54
|
-
close: () => void,
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export type CreateSockdriveFileSystem = (
|
|
58
|
-
endpoint: string,
|
|
59
|
-
ownerId: string,
|
|
60
|
-
driveId: string,
|
|
61
|
-
token: string,
|
|
62
|
-
onOpen: (read: boolean, write: boolean) => void,
|
|
63
|
-
onError: (e: Error) => void
|
|
64
|
-
) => Promise<SockdriveInstance>;
|
|
@@ -1,226 +0,0 @@
|
|
|
1
|
-
import { createFileSystem } from "./fatfs";
|
|
2
|
-
|
|
3
|
-
const toBuffer = require("typedarray-to-buffer");
|
|
4
|
-
import { Drive } from "./sockdrive/drive";
|
|
5
|
-
import { EmModule, Stats as SockdriveStats } from "./sockdrive/types";
|
|
6
|
-
|
|
7
|
-
export interface Driver {
|
|
8
|
-
sectorSize: number,
|
|
9
|
-
numSectors: number,
|
|
10
|
-
readSectors: (sector: number, dst: Uint8Array, cb: (error: Error | null, dst: Uint8Array) => void) => void,
|
|
11
|
-
writeSectors: (sector: number, src: Uint8Array, cb: (error: Error | null) => void) => void,
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
type Callback = (error: Error | null) => void;
|
|
15
|
-
type CallbackT<T> = (error: Error | null, t: T) => void;
|
|
16
|
-
|
|
17
|
-
export type FileDescriptor = number;
|
|
18
|
-
|
|
19
|
-
export interface FileSystemApi {
|
|
20
|
-
mkdir(path: string, cb: Callback): void;
|
|
21
|
-
readdir(path: string, cb: CallbackT<string[]>): void;
|
|
22
|
-
open(path: string, flags: string | number, mode: number, cb: CallbackT<FileDescriptor>): void;
|
|
23
|
-
read(fd: FileDescriptor, buf: Buffer, offset: number,
|
|
24
|
-
length: number, pos: number | null, cb: CallbackT<number>): void;
|
|
25
|
-
write(fd: FileDescriptor, buf: Buffer, offset: number,
|
|
26
|
-
length: number, pos: number | null, cb: CallbackT<number>): void;
|
|
27
|
-
fstat(fd: FileDescriptor, cb: CallbackT<Stats>): void;
|
|
28
|
-
close(fd: FileDescriptor, cb: Callback): void;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export type CreateFileSystemApi = (driver: Driver, opts: {
|
|
32
|
-
ro?: boolean,
|
|
33
|
-
noatime?: boolean,
|
|
34
|
-
modmode?: number,
|
|
35
|
-
umask?: number,
|
|
36
|
-
uid?: number,
|
|
37
|
-
gid?: number,
|
|
38
|
-
}, event: (event: "ready" | "error", reason: Error | null) => void) => FileSystemApi;
|
|
39
|
-
export type CreateSockdriveFileSystem = typeof createSockdriveFileSystem;
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
export class FileSystem {
|
|
43
|
-
fs: FileSystemApi;
|
|
44
|
-
constructor(fs: FileSystemApi) {
|
|
45
|
-
this.fs = fs;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
private promisify<T>(fn: any, ...args: any[]): Promise<T> {
|
|
49
|
-
return new Promise<T>((resolve, reject) => {
|
|
50
|
-
fn.call(this.fs, ...args, (err: Error | null, res: T) => {
|
|
51
|
-
if (!err) {
|
|
52
|
-
resolve(res);
|
|
53
|
-
} else {
|
|
54
|
-
reject(err);
|
|
55
|
-
}
|
|
56
|
-
});
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
mkdir(path: string) {
|
|
61
|
-
return this.promisify<void>(this.fs.mkdir, path);
|
|
62
|
-
}
|
|
63
|
-
readdir(path: string) {
|
|
64
|
-
return this.promisify<string[]>(this.fs.readdir, path);
|
|
65
|
-
}
|
|
66
|
-
fopen(path: string, flags: string | number, mode: number) {
|
|
67
|
-
return this.promisify<FileDescriptor>(this.fs.open, path, flags, mode);
|
|
68
|
-
}
|
|
69
|
-
fread(fd: FileDescriptor, buf: Uint8Array, offset: number,
|
|
70
|
-
length: number, pos: number | null) {
|
|
71
|
-
return this.promisify<number>(this.fs.read, fd, toBuffer(buf),
|
|
72
|
-
offset, length, pos);
|
|
73
|
-
}
|
|
74
|
-
fwrite(fd: FileDescriptor, buf: Uint8Array, offset: number,
|
|
75
|
-
length: number, pos: number | null) {
|
|
76
|
-
return this.promisify<number>(this.fs.write, fd, toBuffer(buf),
|
|
77
|
-
offset, length, pos);
|
|
78
|
-
}
|
|
79
|
-
fstat(fd: FileDescriptor) {
|
|
80
|
-
return this.promisify<Stats>(this.fs.fstat, fd);
|
|
81
|
-
}
|
|
82
|
-
fclose(fd: FileDescriptor) {
|
|
83
|
-
return this.promisify<void>(this.fs.close, fd);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// helpers
|
|
87
|
-
async stat(path: string) {
|
|
88
|
-
const fd: number | null = await (this.fopen(path, "\\r", 0o666)
|
|
89
|
-
.catch((e: Error & { code: string }) => {
|
|
90
|
-
if (e.code === "NOENT") {
|
|
91
|
-
return null;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
throw e;
|
|
95
|
-
}));
|
|
96
|
-
if (fd === null) {
|
|
97
|
-
return null;
|
|
98
|
-
}
|
|
99
|
-
const stat = await this.fstat(fd);
|
|
100
|
-
await this.fclose(fd);
|
|
101
|
-
return stat;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
async isdir(path: string) {
|
|
105
|
-
const stat = await this.stat(path);
|
|
106
|
-
return stat !== null ? stat.isDirectory() : false;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
async exists(path: string) {
|
|
110
|
-
return (await this.stat(path)) !== null;
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
export interface StatsBase<T> {
|
|
115
|
-
isFile(): boolean;
|
|
116
|
-
isDirectory(): boolean;
|
|
117
|
-
isBlockDevice(): boolean;
|
|
118
|
-
isCharacterDevice(): boolean;
|
|
119
|
-
isSymbolicLink(): boolean;
|
|
120
|
-
isFIFO(): boolean;
|
|
121
|
-
isSocket(): boolean;
|
|
122
|
-
dev: T;
|
|
123
|
-
ino: T;
|
|
124
|
-
mode: T;
|
|
125
|
-
nlink: T;
|
|
126
|
-
uid: T;
|
|
127
|
-
gid: T;
|
|
128
|
-
rdev: T;
|
|
129
|
-
size: T;
|
|
130
|
-
blksize: T;
|
|
131
|
-
blocks: T;
|
|
132
|
-
atimeMs: T;
|
|
133
|
-
mtimeMs: T;
|
|
134
|
-
ctimeMs: T;
|
|
135
|
-
birthtimeMs: T;
|
|
136
|
-
atime: Date;
|
|
137
|
-
mtime: Date;
|
|
138
|
-
ctime: Date;
|
|
139
|
-
birthtime: Date;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
export interface Stats extends StatsBase<number> { }
|
|
143
|
-
|
|
144
|
-
export async function createSockdriveFileSystem(endpoint: string,
|
|
145
|
-
ownerId: string,
|
|
146
|
-
driveId: string,
|
|
147
|
-
token: string,
|
|
148
|
-
onOpen: (read: boolean, write: boolean) => void = () => { },
|
|
149
|
-
onError: (e: Error) => void = () => { }) {
|
|
150
|
-
const stats: SockdriveStats = {
|
|
151
|
-
read: 0,
|
|
152
|
-
write: 0,
|
|
153
|
-
readTotalTime: 0,
|
|
154
|
-
cacheHit: 0,
|
|
155
|
-
cacheMiss: 0,
|
|
156
|
-
cacheUsed: 0,
|
|
157
|
-
};
|
|
158
|
-
|
|
159
|
-
const sectorSize = 512;
|
|
160
|
-
const module: EmModule = {
|
|
161
|
-
HEAPU8: new Uint8Array(sectorSize),
|
|
162
|
-
};
|
|
163
|
-
|
|
164
|
-
let drive: Drive | null = null;
|
|
165
|
-
const fs = await new Promise<FileSystemApi>((resolve, reject) => {
|
|
166
|
-
drive = new Drive(endpoint, ownerId, driveId, token, stats, module);
|
|
167
|
-
drive.onOpen((read, write, imageSize) => {
|
|
168
|
-
// TODO: fatfs should respect boot record section
|
|
169
|
-
const MBR_OFFSET = 63;
|
|
170
|
-
const driver: Driver = {
|
|
171
|
-
sectorSize,
|
|
172
|
-
numSectors: imageSize / sectorSize,
|
|
173
|
-
readSectors: function(start, dst, cb) {
|
|
174
|
-
(async () => {
|
|
175
|
-
start += MBR_OFFSET;
|
|
176
|
-
// TODO we can avoid copying in dst.set
|
|
177
|
-
for (let i = 0; i < dst.length / sectorSize; ++i) {
|
|
178
|
-
if (drive.read(start + i, 0, true) !== 0) {
|
|
179
|
-
const readCode = await drive.read(start + i, 0, false);
|
|
180
|
-
if (readCode !== 0) {
|
|
181
|
-
cb(new Error("Read error, code: " + readCode), dst);
|
|
182
|
-
return;
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
dst.set(module.HEAPU8.slice(0, sectorSize), i * sectorSize);
|
|
186
|
-
}
|
|
187
|
-
})()
|
|
188
|
-
.then(() => cb(null, dst))
|
|
189
|
-
.catch((e) => cb(e, dst));
|
|
190
|
-
},
|
|
191
|
-
writeSectors: function(start, data, cb) {
|
|
192
|
-
start += MBR_OFFSET;
|
|
193
|
-
for (let i = 0; i < data.length / sectorSize; ++i) {
|
|
194
|
-
module.HEAPU8.set(data.slice(i * sectorSize, (i + 1) * sectorSize), 0);
|
|
195
|
-
const writeCode = drive.write(start + i, 0);
|
|
196
|
-
if (writeCode !== 0) {
|
|
197
|
-
cb(new Error("Write error, code: " + 0));
|
|
198
|
-
return;
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
cb(null);
|
|
202
|
-
},
|
|
203
|
-
};
|
|
204
|
-
const fs = (createFileSystem as any as CreateFileSystemApi)(driver, {}, (ev, reason) => {
|
|
205
|
-
if (ev === "ready") {
|
|
206
|
-
resolve(fs);
|
|
207
|
-
} else {
|
|
208
|
-
console.error(ev, reason);
|
|
209
|
-
reject(reason);
|
|
210
|
-
}
|
|
211
|
-
});
|
|
212
|
-
onOpen(read, write);
|
|
213
|
-
});
|
|
214
|
-
drive.onError(onError);
|
|
215
|
-
});
|
|
216
|
-
|
|
217
|
-
return {
|
|
218
|
-
stats,
|
|
219
|
-
fs: new FileSystem(fs),
|
|
220
|
-
close: () => drive?.close(),
|
|
221
|
-
};
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
(window as any).createSockdriveFileSystem = createSockdriveFileSystem;
|
|
226
|
-
(window as any).createFileSystem = createFileSystem;
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
import { EmModule, Handle, Ptr, Stats } from "./sockdrive/types";
|
|
2
|
-
import { Drive } from "./sockdrive/drive";
|
|
3
|
-
|
|
4
|
-
interface Template {
|
|
5
|
-
name: string,
|
|
6
|
-
size: number,
|
|
7
|
-
heads: number,
|
|
8
|
-
cylinders: number,
|
|
9
|
-
sectors: number,
|
|
10
|
-
sector_size: number,
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
declare const Module: EmModule & any;
|
|
14
|
-
|
|
15
|
-
(function() {
|
|
16
|
-
let seq = 0;
|
|
17
|
-
const mapping: { [handle: Handle]: Drive } = {};
|
|
18
|
-
const templates: { [handle: number]: Template } = {};
|
|
19
|
-
const stats: Stats = {
|
|
20
|
-
read: 0,
|
|
21
|
-
write: 0,
|
|
22
|
-
readTotalTime: 0,
|
|
23
|
-
cacheHit: 0,
|
|
24
|
-
cacheMiss: 0,
|
|
25
|
-
cacheUsed: 0,
|
|
26
|
-
};
|
|
27
|
-
Module.sockdrive = {
|
|
28
|
-
stats,
|
|
29
|
-
onError: (e: Error) => {
|
|
30
|
-
console.error(e);
|
|
31
|
-
},
|
|
32
|
-
onOpen: (drive: string, read: boolean, write: boolean) => {
|
|
33
|
-
// noop
|
|
34
|
-
},
|
|
35
|
-
onPreloadProgress: (dirve: string, restBytes: number) => {
|
|
36
|
-
// noop
|
|
37
|
-
},
|
|
38
|
-
open: async (url: string, owner: string, name: string, token: string): Promise<Handle> => {
|
|
39
|
-
const response = await fetch(url.replace("wss://", "https://")
|
|
40
|
-
.replace("ws://", "http://") + "/template/" + owner + "/" + name);
|
|
41
|
-
const template = await response.json();
|
|
42
|
-
if (template.error) {
|
|
43
|
-
throw new Error(template.error);
|
|
44
|
-
}
|
|
45
|
-
seq++;
|
|
46
|
-
templates[seq] = template;
|
|
47
|
-
return new Promise<Handle>((resolve, reject) => {
|
|
48
|
-
mapping[seq] = new Drive(url, owner, name, token, stats, Module);
|
|
49
|
-
mapping[seq].onOpen((read, write, imageSize, preloadQueue) => {
|
|
50
|
-
Module.sockdrive.onOpen(owner + "/" + name, read, write, imageSize, preloadQueue);
|
|
51
|
-
resolve(seq);
|
|
52
|
-
});
|
|
53
|
-
mapping[seq].onError((e) => {
|
|
54
|
-
Module.sockdrive.onError(e);
|
|
55
|
-
reject(e);
|
|
56
|
-
});
|
|
57
|
-
mapping[seq].onPreloadProgress((restBytes) => {
|
|
58
|
-
Module.sockdrive.onPreloadProgress(owner + "/" + name, restBytes);
|
|
59
|
-
});
|
|
60
|
-
});
|
|
61
|
-
},
|
|
62
|
-
read: (handle: Handle, sector: number, buffer: Ptr, sync: boolean): Promise<number> | number => {
|
|
63
|
-
if (mapping[handle]) {
|
|
64
|
-
return mapping[handle].read(sector, buffer, sync);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
console.error("ERROR! sockdrive handle", handle, "not found");
|
|
68
|
-
return sync ? 1 : Promise.resolve(1);
|
|
69
|
-
},
|
|
70
|
-
write: (handle: Handle, sector: number, buffer: Ptr): number => {
|
|
71
|
-
if (mapping[handle]) {
|
|
72
|
-
return mapping[handle].write(sector, buffer);
|
|
73
|
-
}
|
|
74
|
-
console.error("ERROR! sockdrive handle", handle, "not found");
|
|
75
|
-
return 1;
|
|
76
|
-
},
|
|
77
|
-
close: (handle: Handle) => {
|
|
78
|
-
if (mapping[handle]) {
|
|
79
|
-
Module._free(mapping[handle].readAheadBuffer);
|
|
80
|
-
mapping[handle].close();
|
|
81
|
-
delete mapping[handle];
|
|
82
|
-
}
|
|
83
|
-
},
|
|
84
|
-
size: (handle: Handle) => {
|
|
85
|
-
return templates[handle]?.size ?? 0;
|
|
86
|
-
},
|
|
87
|
-
sector_size: (handle: Handle) => {
|
|
88
|
-
return templates[handle]?.sector_size ?? 512;
|
|
89
|
-
},
|
|
90
|
-
heads: (handle: Handle) => {
|
|
91
|
-
return templates[handle]?.heads ?? 1;
|
|
92
|
-
},
|
|
93
|
-
cylinders: (handle: Handle) => {
|
|
94
|
-
return templates[handle]?.cylinders ?? 520;
|
|
95
|
-
},
|
|
96
|
-
sectors: (handle: Handle) => {
|
|
97
|
-
return templates[handle]?.sectors ?? 63;
|
|
98
|
-
},
|
|
99
|
-
};
|
|
100
|
-
})();
|
|
@@ -1,289 +0,0 @@
|
|
|
1
|
-
import { FileSystem, FileSystemApi, CreateFileSystemApi, Driver, CreateSockdriveFileSystem } from "../sockdrive-fat";
|
|
2
|
-
import { Drive } from "../sockdrive/drive";
|
|
3
|
-
import { EmModule, Stats } from "../sockdrive/types";
|
|
4
|
-
|
|
5
|
-
declare const createFileSystem: CreateFileSystemApi;
|
|
6
|
-
declare const createSockdriveFileSystem: CreateSockdriveFileSystem;
|
|
7
|
-
|
|
8
|
-
const baseDir = "/test";
|
|
9
|
-
const file = baseDir + "/Simple File.txt";
|
|
10
|
-
|
|
11
|
-
async function runTests() {
|
|
12
|
-
const assert = chai.assert;
|
|
13
|
-
function createDriver(orig: Uint8Array): Driver {
|
|
14
|
-
const image = orig.slice(0, orig.length);
|
|
15
|
-
const sectorSize = 512;
|
|
16
|
-
return {
|
|
17
|
-
sectorSize,
|
|
18
|
-
numSectors: image.length / 512,
|
|
19
|
-
readSectors: function(sector, dst, cb) {
|
|
20
|
-
dst.set(image.slice(sector * sectorSize, sector * sectorSize + dst.length));
|
|
21
|
-
cb(null, dst);
|
|
22
|
-
},
|
|
23
|
-
writeSectors: function(sector, data, cb) {
|
|
24
|
-
image.set(data, sector * sectorSize);
|
|
25
|
-
cb(null);
|
|
26
|
-
},
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const loadImage = async (url: string) => new Uint8Array(await (await fetch(url)).arrayBuffer());
|
|
31
|
-
const images: { [key: string]: Uint8Array } = {
|
|
32
|
-
fat12: await loadImage("test/fat12.img"),
|
|
33
|
-
fat16: await loadImage("test/fat16.img"),
|
|
34
|
-
fat32: await loadImage("test/fat32.img"),
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
const writeBuf = new Uint8Array(4096 * 4);
|
|
38
|
-
for (let i = 0; i < writeBuf.length; ++i) {
|
|
39
|
-
writeBuf[i] = i % 256;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const testRead = async (fs: FileSystem) => {
|
|
43
|
-
const readBuf = new Uint8Array(writeBuf.length);
|
|
44
|
-
const fd = await fs.fopen(file, "r", 0o666);
|
|
45
|
-
assert.equal((await fs.fstat(fd)).size, writeBuf.length);
|
|
46
|
-
assert.equal(await fs.fread(fd, readBuf, 0, readBuf.length, 0), readBuf.length);
|
|
47
|
-
assert.deepEqual(readBuf, writeBuf);
|
|
48
|
-
await fs.fclose(fd);
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
const testOpenWriteStatClose = async (fs: FileSystem) => {
|
|
52
|
-
try {
|
|
53
|
-
await fs.mkdir(baseDir);
|
|
54
|
-
} catch (e) {
|
|
55
|
-
// ignore if exists
|
|
56
|
-
}
|
|
57
|
-
const fd = await fs.fopen(file, "w", 0o666);
|
|
58
|
-
assert.ok(fd);
|
|
59
|
-
assert.equal(await fs.fwrite(fd, writeBuf, 0, writeBuf.length, null), writeBuf.length);
|
|
60
|
-
await fs.fclose(fd);
|
|
61
|
-
await testRead(fs);
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
const testHelpers = async (fs: FileSystem) => {
|
|
65
|
-
assert.isFalse(await fs.exists("/not-exists"), "/not-exists not exits");
|
|
66
|
-
assert.isTrue(await fs.exists(baseDir), "baseDir exists");
|
|
67
|
-
assert.isTrue(await fs.exists(file), "file exists");
|
|
68
|
-
assert.isTrue(await fs.isdir(baseDir), "baseDir is dir");
|
|
69
|
-
assert.isFalse(await fs.isdir(file), "file is file");
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
for (const name of Object.keys(images)) {
|
|
73
|
-
const driver = () => createDriver(images[name]);
|
|
74
|
-
const fs = () => new Promise<FileSystemApi>((resolve, reject) => {
|
|
75
|
-
const fs = createFileSystem(driver(), {}, (ev, reason) => {
|
|
76
|
-
if (ev === "ready") {
|
|
77
|
-
resolve(fs);
|
|
78
|
-
} else {
|
|
79
|
-
console.error(ev, reason);
|
|
80
|
-
reject(reason);
|
|
81
|
-
}
|
|
82
|
-
});
|
|
83
|
-
});
|
|
84
|
-
suite(name + ".driver");
|
|
85
|
-
|
|
86
|
-
test("create driver", () => {
|
|
87
|
-
assert.exists(driver());
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
test("create fs", async () => {
|
|
91
|
-
assert.exists(await fs());
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
const testFs = (name: string, fn: (fs: FileSystem) => Promise<void>) => {
|
|
95
|
-
test(name, async () => fn(new FileSystem(await fs())));
|
|
96
|
-
};
|
|
97
|
-
|
|
98
|
-
testFs("api", async (fs) => {
|
|
99
|
-
for (const method of [
|
|
100
|
-
"mkdir", "readdir",
|
|
101
|
-
// "rename", "unlink", "rmdir",
|
|
102
|
-
"fclose", "fopen", "fwrite", "fread", "fstat",
|
|
103
|
-
"stat", "exists", "isdir",
|
|
104
|
-
// "fsync",
|
|
105
|
-
// "ftruncate", "truncate",
|
|
106
|
-
// "readFile", "writeFile", "appendFile",
|
|
107
|
-
|
|
108
|
-
// "chown", "lchown", "fchown",
|
|
109
|
-
// "chmod", "lchmod", "fchmod",
|
|
110
|
-
// "utimes", "futimes",
|
|
111
|
-
// "lstat", "fstat",
|
|
112
|
-
// "link", "symlink", "readlink", "realpath",
|
|
113
|
-
|
|
114
|
-
// 'watchfile','unwatchfile','watch'
|
|
115
|
-
]) {
|
|
116
|
-
assert.ok(method in fs, "fs." + method + " has implementation.");
|
|
117
|
-
};
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
testFs("readdir", async (fs) => {
|
|
121
|
-
const files = await fs.readdir("/");
|
|
122
|
-
assert.ok(Array.isArray(files));
|
|
123
|
-
assert.ok(files.length === 0, "image is empty");
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
testFs("mkdir", async (fs) => {
|
|
127
|
-
await fs.mkdir(baseDir);
|
|
128
|
-
assert.ok((await fs.readdir(baseDir)).length === 0, "base dir is empty");
|
|
129
|
-
const root = await fs.readdir("/");
|
|
130
|
-
assert.ok(root.length === 1, "root have 1 folder");
|
|
131
|
-
assert.equal("/" + root[0], baseDir);
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
testFs("open/write/stat/read/close", testOpenWriteStatClose);
|
|
135
|
-
|
|
136
|
-
testFs("exists/isdir", async (fs) => {
|
|
137
|
-
await testOpenWriteStatClose(fs);
|
|
138
|
-
await testHelpers(fs);
|
|
139
|
-
});
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
suite("Drive 127.0.0.1:8001");
|
|
143
|
-
|
|
144
|
-
const testDrive = (name: string,
|
|
145
|
-
fn: (drive: Drive, module: EmModule, stats: Stats, preloadQueue: number[]) => Promise<void>,
|
|
146
|
-
preload = false) => {
|
|
147
|
-
test(name, async () => {
|
|
148
|
-
const module: EmModule = {
|
|
149
|
-
HEAPU8: new Uint8Array(512),
|
|
150
|
-
};
|
|
151
|
-
|
|
152
|
-
const stats: Stats = {
|
|
153
|
-
read: 0,
|
|
154
|
-
write: 0,
|
|
155
|
-
readTotalTime: 0,
|
|
156
|
-
cacheHit: 0,
|
|
157
|
-
cacheMiss: 0,
|
|
158
|
-
cacheUsed: 0,
|
|
159
|
-
};
|
|
160
|
-
|
|
161
|
-
const drive = new Drive("ws://127.0.0.1:8001", "system", "test", "", stats, module, preload);
|
|
162
|
-
let preloadQueue: number[] = [];
|
|
163
|
-
await new Promise<void>((resolve, reject) => {
|
|
164
|
-
drive.onOpen((read, write, imageSize, preload) => {
|
|
165
|
-
if (!preload) {
|
|
166
|
-
assert.equal(0, preload.length);
|
|
167
|
-
}
|
|
168
|
-
preloadQueue = [...preload];
|
|
169
|
-
resolve();
|
|
170
|
-
});
|
|
171
|
-
drive.onError((e) => {
|
|
172
|
-
reject(e);
|
|
173
|
-
});
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
await fn(drive, module, stats, preloadQueue);
|
|
177
|
-
await drive.close();
|
|
178
|
-
});
|
|
179
|
-
};
|
|
180
|
-
|
|
181
|
-
testDrive("read sector", async (drive, module, stats) => {
|
|
182
|
-
assert.equal(await drive.read(0, 0, false), 0);
|
|
183
|
-
assert.deepEqual(module.HEAPU8.slice(0, 10), new Uint8Array([51, 192, 142, 208, 188, 0, 124, 251, 80, 7]));
|
|
184
|
-
assert.equal(1, stats.cacheMiss, "cache miss");
|
|
185
|
-
assert.equal(0, stats.cacheHit, "cache hit");
|
|
186
|
-
|
|
187
|
-
assert.equal(await drive.read(8192, 0, false), 0);
|
|
188
|
-
assert.deepEqual(module.HEAPU8.slice(0, 10), new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0]));
|
|
189
|
-
assert.equal(2, stats.cacheMiss, "cache miss");
|
|
190
|
-
assert.equal(0, stats.cacheHit, "cache hit");
|
|
191
|
-
|
|
192
|
-
assert.equal(await drive.read(8448, 0, false), 0);
|
|
193
|
-
assert.deepEqual(module.HEAPU8.slice(256, 256 + 10), new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]));
|
|
194
|
-
assert.equal(2, stats.cacheMiss, "cache miss");
|
|
195
|
-
assert.equal(1, stats.cacheHit, "cache hit");
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
testDrive("read cache", async (drive, module, stats) => {
|
|
199
|
-
assert.equal(await drive.read(0, 0, false), 0);
|
|
200
|
-
assert.equal(0, stats.cacheHit, "cache hit");
|
|
201
|
-
assert.equal(1, stats.cacheMiss, "cache miss");
|
|
202
|
-
|
|
203
|
-
for (let i = 0; i < 128; ++i) {
|
|
204
|
-
assert.equal(await drive.read(1 + i, 0, true), 0);
|
|
205
|
-
assert.equal(i + 1, stats.cacheHit, "cache hit");
|
|
206
|
-
assert.equal(1, stats.cacheMiss, "cache miss");
|
|
207
|
-
if (i == 62) {
|
|
208
|
-
assert.deepEqual(module.HEAPU8.slice(0, 10),
|
|
209
|
-
new Uint8Array([235, 88, 144, 77, 83, 87, 73, 78, 52, 46]));
|
|
210
|
-
}
|
|
211
|
-
if (i == 127) {
|
|
212
|
-
assert.deepEqual(module.HEAPU8.slice(0, 10),
|
|
213
|
-
new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0]));
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
});
|
|
217
|
-
|
|
218
|
-
testDrive("preload sectors", async (drive, module, stats, preloadQueue) => {
|
|
219
|
-
assert.ok(preloadQueue.length >= 2);
|
|
220
|
-
let _0 = false;
|
|
221
|
-
let _8192 = false;
|
|
222
|
-
for (const next of preloadQueue) {
|
|
223
|
-
_0 = _0 || next === 0;
|
|
224
|
-
_8192 = _8192 || next === 8192;
|
|
225
|
-
}
|
|
226
|
-
assert.ok(_0 && _8192);
|
|
227
|
-
|
|
228
|
-
await new Promise<void>((resolve) => setTimeout(resolve, 1000));
|
|
229
|
-
|
|
230
|
-
assert.equal(drive.read(0, 0, true), 0, "sector 0 in cache");
|
|
231
|
-
assert.deepEqual(module.HEAPU8.slice(0, 10), new Uint8Array([51, 192, 142, 208, 188, 0, 124, 251, 80, 7]));
|
|
232
|
-
|
|
233
|
-
assert.equal(await drive.read(8192, 0, true), 0, "sector 8192 in cache");
|
|
234
|
-
assert.deepEqual(module.HEAPU8.slice(0, 10), new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0]));
|
|
235
|
-
|
|
236
|
-
assert.equal(await drive.read(8448, 0, true), 0, "sector 8448 in cache");
|
|
237
|
-
assert.deepEqual(module.HEAPU8.slice(256, 256 + 10), new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]));
|
|
238
|
-
|
|
239
|
-
assert.equal(3, stats.cacheHit, "cache hit");
|
|
240
|
-
assert.equal(0, stats.cacheMiss, "cache miss");
|
|
241
|
-
}, true);
|
|
242
|
-
|
|
243
|
-
suite("sockdrive 127.0.0.1:8001");
|
|
244
|
-
|
|
245
|
-
test("error on wrong drive name", (done) => {
|
|
246
|
-
createSockdriveFileSystem("ws://127.0.0.1:8001", "system", "not-exists", "",
|
|
247
|
-
() => { },
|
|
248
|
-
(e) => {
|
|
249
|
-
assert.strictEqual(e.message, "Err: no such drive");
|
|
250
|
-
done();
|
|
251
|
-
});
|
|
252
|
-
});
|
|
253
|
-
|
|
254
|
-
const testSd = (name: string, fn: (fs: FileSystem) => Promise<void>, writeCheck?: number[]) => {
|
|
255
|
-
test(name, async () => {
|
|
256
|
-
const { stats, fs, close } = await createSockdriveFileSystem("ws://127.0.0.1:8001", "system", "test", "",
|
|
257
|
-
(read, write) => {
|
|
258
|
-
assert.isTrue(read, "read access");
|
|
259
|
-
assert.isTrue(write, "write access");
|
|
260
|
-
});
|
|
261
|
-
await fn(fs);
|
|
262
|
-
await new Promise<void>((resolve) => {
|
|
263
|
-
setTimeout(resolve, 16);
|
|
264
|
-
});
|
|
265
|
-
await close();
|
|
266
|
-
if (writeCheck) {
|
|
267
|
-
assert.isTrue(writeCheck.findIndex((v) => v === stats.write) >= 0,
|
|
268
|
-
"write check " + stats.write + " in " + writeCheck);
|
|
269
|
-
}
|
|
270
|
-
});
|
|
271
|
-
};
|
|
272
|
-
|
|
273
|
-
testSd("connect", async (fs) => {
|
|
274
|
-
assert.ok(fs);
|
|
275
|
-
});
|
|
276
|
-
|
|
277
|
-
testSd("readdir /", async (fs) => {
|
|
278
|
-
assert.ok(await fs.readdir("/"));
|
|
279
|
-
});
|
|
280
|
-
|
|
281
|
-
testSd("open/write/stat/read/close", testOpenWriteStatClose);
|
|
282
|
-
testSd("reconnect stat/read/close", testRead);
|
|
283
|
-
testSd("exists/isdir", testHelpers);
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
mocha.run();
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
(window as any).runTests = runTests;
|