@gjsify/web-globals 0.0.3 → 0.1.0
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 +25 -5
- package/lib/esm/index.js +52 -0
- package/lib/types/index.d.ts +14 -0
- package/package.json +32 -25
- package/src/index.spec.ts +273 -6
- package/src/index.ts +66 -3
- package/src/test.mts +1 -1
- package/tsconfig.json +22 -9
- package/tsconfig.tsbuildinfo +1 -0
- package/lib/cjs/index.js +0 -2
- package/test.gjs.mjs +0 -34720
- package/test.node.mjs +0 -307
- package/tsconfig.types.json +0 -8
package/README.md
CHANGED
|
@@ -1,6 +1,26 @@
|
|
|
1
|
-
# @gjsify/web-
|
|
1
|
+
# @gjsify/web-globals
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
Re-exports Web API globals from dom-events and abort-controller for GJS.
|
|
4
|
+
|
|
5
|
+
Part of the [gjsify](https://github.com/gjsify/gjsify) project — Node.js and Web APIs for GJS (GNOME JavaScript).
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @gjsify/web-globals
|
|
11
|
+
# or
|
|
12
|
+
yarn add @gjsify/web-globals
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
import '@gjsify/web-globals';
|
|
19
|
+
|
|
20
|
+
// Web API globals like Event, CustomEvent, EventTarget,
|
|
21
|
+
// AbortController, and AbortSignal are now available.
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## License
|
|
25
|
+
|
|
26
|
+
MIT
|
package/lib/esm/index.js
CHANGED
|
@@ -1,2 +1,54 @@
|
|
|
1
|
+
import "@gjsify/dom-exception";
|
|
1
2
|
import "@gjsify/dom-events";
|
|
2
3
|
import "@gjsify/abort-controller";
|
|
4
|
+
import "@gjsify/web-streams";
|
|
5
|
+
import "@gjsify/compression-streams";
|
|
6
|
+
import "@gjsify/webcrypto";
|
|
7
|
+
import "@gjsify/eventsource";
|
|
8
|
+
import { URL, URLSearchParams } from "@gjsify/url";
|
|
9
|
+
if (typeof globalThis.URL !== "function") {
|
|
10
|
+
Object.defineProperty(globalThis, "URL", { value: URL, writable: true, configurable: true });
|
|
11
|
+
}
|
|
12
|
+
if (typeof globalThis.URLSearchParams !== "function") {
|
|
13
|
+
Object.defineProperty(globalThis, "URLSearchParams", { value: URLSearchParams, writable: true, configurable: true });
|
|
14
|
+
}
|
|
15
|
+
import { Blob, File } from "@gjsify/buffer";
|
|
16
|
+
if (typeof globalThis.Blob !== "function") {
|
|
17
|
+
Object.defineProperty(globalThis, "Blob", { value: Blob, writable: true, configurable: true });
|
|
18
|
+
}
|
|
19
|
+
if (typeof globalThis.File !== "function") {
|
|
20
|
+
Object.defineProperty(globalThis, "File", { value: File, writable: true, configurable: true });
|
|
21
|
+
}
|
|
22
|
+
import { FormData } from "@gjsify/formdata";
|
|
23
|
+
if (typeof globalThis.FormData !== "function") {
|
|
24
|
+
Object.defineProperty(globalThis, "FormData", { value: FormData, writable: true, configurable: true });
|
|
25
|
+
}
|
|
26
|
+
import { performance, PerformanceObserver } from "@gjsify/perf_hooks";
|
|
27
|
+
if (!globalThis.performance) {
|
|
28
|
+
Object.defineProperty(globalThis, "performance", { value: performance, writable: true, configurable: true });
|
|
29
|
+
}
|
|
30
|
+
if (typeof globalThis.PerformanceObserver !== "function") {
|
|
31
|
+
Object.defineProperty(globalThis, "PerformanceObserver", { value: PerformanceObserver, writable: true, configurable: true });
|
|
32
|
+
}
|
|
33
|
+
import { DOMException } from "@gjsify/dom-exception";
|
|
34
|
+
import { Event, EventTarget, CustomEvent } from "@gjsify/dom-events";
|
|
35
|
+
import { AbortController, AbortSignal } from "@gjsify/abort-controller";
|
|
36
|
+
import { URL as URL2, URLSearchParams as URLSearchParams2 } from "@gjsify/url";
|
|
37
|
+
import { Blob as Blob2, File as File2 } from "@gjsify/buffer";
|
|
38
|
+
import { FormData as FormData2 } from "@gjsify/formdata";
|
|
39
|
+
import { performance as performance2, PerformanceObserver as PerformanceObserver2 } from "@gjsify/perf_hooks";
|
|
40
|
+
export {
|
|
41
|
+
AbortController,
|
|
42
|
+
AbortSignal,
|
|
43
|
+
Blob2 as Blob,
|
|
44
|
+
CustomEvent,
|
|
45
|
+
DOMException,
|
|
46
|
+
Event,
|
|
47
|
+
EventTarget,
|
|
48
|
+
File2 as File,
|
|
49
|
+
FormData2 as FormData,
|
|
50
|
+
PerformanceObserver2 as PerformanceObserver,
|
|
51
|
+
URL2 as URL,
|
|
52
|
+
URLSearchParams2 as URLSearchParams,
|
|
53
|
+
performance2 as performance
|
|
54
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import '@gjsify/dom-exception';
|
|
2
|
+
import '@gjsify/dom-events';
|
|
3
|
+
import '@gjsify/abort-controller';
|
|
4
|
+
import '@gjsify/web-streams';
|
|
5
|
+
import '@gjsify/compression-streams';
|
|
6
|
+
import '@gjsify/webcrypto';
|
|
7
|
+
import '@gjsify/eventsource';
|
|
8
|
+
export { DOMException } from '@gjsify/dom-exception';
|
|
9
|
+
export { Event, EventTarget, CustomEvent } from '@gjsify/dom-events';
|
|
10
|
+
export { AbortController, AbortSignal } from '@gjsify/abort-controller';
|
|
11
|
+
export { URL, URLSearchParams } from '@gjsify/url';
|
|
12
|
+
export { Blob, File } from '@gjsify/buffer';
|
|
13
|
+
export { FormData } from '@gjsify/formdata';
|
|
14
|
+
export { performance, PerformanceObserver } from '@gjsify/perf_hooks';
|
package/package.json
CHANGED
|
@@ -1,42 +1,49 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gjsify/web-globals",
|
|
3
|
-
"version": "0.0
|
|
4
|
-
"description": "Web
|
|
5
|
-
"main": "lib/cjs/index.js",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Unified Web API globals for GJS — single import for all Web standard polyfills",
|
|
6
5
|
"module": "lib/esm/index.js",
|
|
6
|
+
"types": "lib/types/index.d.ts",
|
|
7
7
|
"exports": {
|
|
8
8
|
".": {
|
|
9
|
-
"
|
|
10
|
-
|
|
11
|
-
"default": "./lib/esm/index.js"
|
|
12
|
-
},
|
|
13
|
-
"require": {
|
|
14
|
-
"types": "./lib/types/index.d.ts",
|
|
15
|
-
"default": "./lib/cjs/index.js"
|
|
16
|
-
}
|
|
9
|
+
"types": "./lib/types/index.d.ts",
|
|
10
|
+
"default": "./lib/esm/index.js"
|
|
17
11
|
}
|
|
18
12
|
},
|
|
19
13
|
"scripts": {
|
|
20
|
-
"clear": "rm -rf lib tsconfig.tsbuildinfo tsconfig.types.tsbuildinfo || exit 0",
|
|
21
|
-
"
|
|
22
|
-
"build": "yarn
|
|
14
|
+
"clear": "rm -rf lib tsconfig.tsbuildinfo tsconfig.types.tsbuildinfo test.gjs.mjs test.node.mjs || exit 0",
|
|
15
|
+
"check": "tsc --noEmit",
|
|
16
|
+
"build": "yarn build:gjsify && yarn build:types",
|
|
23
17
|
"build:gjsify": "gjsify build --library 'src/**/*.{ts,js}' --exclude 'src/**/*.spec.{mts,ts}' 'src/test.{mts,ts}'",
|
|
24
|
-
"build:types": "tsc
|
|
25
|
-
"build:test": "yarn build:test:gjs
|
|
18
|
+
"build:types": "tsc",
|
|
19
|
+
"build:test": "yarn build:test:gjs",
|
|
26
20
|
"build:test:gjs": "gjsify build src/test.mts --app gjs --outfile test.gjs.mjs",
|
|
27
|
-
"
|
|
28
|
-
"test": "
|
|
29
|
-
"test:gjs": "gjs -m test.gjs.mjs",
|
|
30
|
-
"test:node": "node test.node.mjs"
|
|
21
|
+
"test": "yarn build:gjsify && yarn build:test && yarn test:gjs",
|
|
22
|
+
"test:gjs": "gjs -m test.gjs.mjs"
|
|
31
23
|
},
|
|
32
24
|
"keywords": [
|
|
33
25
|
"gjs",
|
|
34
|
-
"
|
|
35
|
-
"
|
|
26
|
+
"web-globals",
|
|
27
|
+
"polyfill",
|
|
28
|
+
"web-apis"
|
|
36
29
|
],
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"@gjsify/abort-controller": "^0.1.0",
|
|
32
|
+
"@gjsify/buffer": "^0.1.0",
|
|
33
|
+
"@gjsify/compression-streams": "^0.1.0",
|
|
34
|
+
"@gjsify/dom-events": "^0.1.0",
|
|
35
|
+
"@gjsify/dom-exception": "^0.1.0",
|
|
36
|
+
"@gjsify/eventsource": "^0.1.0",
|
|
37
|
+
"@gjsify/formdata": "^0.1.0",
|
|
38
|
+
"@gjsify/perf_hooks": "^0.1.0",
|
|
39
|
+
"@gjsify/url": "^0.1.0",
|
|
40
|
+
"@gjsify/web-streams": "^0.1.0",
|
|
41
|
+
"@gjsify/webcrypto": "^0.1.0"
|
|
42
|
+
},
|
|
37
43
|
"devDependencies": {
|
|
38
|
-
"@gjsify/cli": "^0.0
|
|
39
|
-
"@gjsify/unit": "^0.0
|
|
40
|
-
"@types/node": "^
|
|
44
|
+
"@gjsify/cli": "^0.1.0",
|
|
45
|
+
"@gjsify/unit": "^0.1.0",
|
|
46
|
+
"@types/node": "^25.5.0",
|
|
47
|
+
"typescript": "^6.0.2"
|
|
41
48
|
}
|
|
42
49
|
}
|
package/src/index.spec.ts
CHANGED
|
@@ -1,9 +1,276 @@
|
|
|
1
|
+
// Tests for @gjsify/web-globals — verify all Web API globals are registered
|
|
1
2
|
import { describe, it, expect } from '@gjsify/unit';
|
|
2
3
|
|
|
4
|
+
// Side-effect import — registers all globals
|
|
5
|
+
import '@gjsify/web-globals';
|
|
6
|
+
|
|
3
7
|
export default async () => {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
await describe('web-globals', async () => {
|
|
9
|
+
|
|
10
|
+
// ==================== DOMException ====================
|
|
11
|
+
await describe('DOMException', async () => {
|
|
12
|
+
await it('should be available as global', async () => {
|
|
13
|
+
expect(typeof globalThis.DOMException).toBe('function');
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
await it('should be constructable with message and name', async () => {
|
|
17
|
+
const err = new DOMException('test', 'AbortError');
|
|
18
|
+
expect(err.message).toBe('test');
|
|
19
|
+
expect(err.name).toBe('AbortError');
|
|
20
|
+
expect(err.code).toBe(20);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
await it('should have standard error codes', async () => {
|
|
24
|
+
expect(new DOMException('', 'NotFoundError').code).toBe(8);
|
|
25
|
+
expect(new DOMException('', 'NotSupportedError').code).toBe(9);
|
|
26
|
+
expect(new DOMException('', 'InvalidStateError').code).toBe(11);
|
|
27
|
+
expect(new DOMException('', 'SyntaxError').code).toBe(12);
|
|
28
|
+
expect(new DOMException('', 'TimeoutError').code).toBe(23);
|
|
29
|
+
expect(new DOMException('', 'DataCloneError').code).toBe(25);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
await it('should be an instance of Error', async () => {
|
|
33
|
+
const err = new DOMException('test');
|
|
34
|
+
expect(err instanceof Error).toBe(true);
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// ==================== DOM Events ====================
|
|
39
|
+
await describe('DOM Events', async () => {
|
|
40
|
+
await it('Event should be available as global', async () => {
|
|
41
|
+
expect(typeof globalThis.Event).toBe('function');
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
await it('EventTarget should be available as global', async () => {
|
|
45
|
+
expect(typeof globalThis.EventTarget).toBe('function');
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
await it('Event should be constructable', async () => {
|
|
49
|
+
const event = new Event('test');
|
|
50
|
+
expect(event.type).toBe('test');
|
|
51
|
+
expect(event.bubbles).toBe(false);
|
|
52
|
+
expect(event.cancelable).toBe(false);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
await it('EventTarget should dispatch events', async () => {
|
|
56
|
+
const target = new EventTarget();
|
|
57
|
+
let called = false;
|
|
58
|
+
target.addEventListener('test', () => { called = true; });
|
|
59
|
+
target.dispatchEvent(new Event('test'));
|
|
60
|
+
expect(called).toBe(true);
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
// ==================== AbortController / AbortSignal ====================
|
|
65
|
+
await describe('AbortController', async () => {
|
|
66
|
+
await it('AbortController should be available as global', async () => {
|
|
67
|
+
expect(typeof globalThis.AbortController).toBe('function');
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
await it('AbortSignal should be available as global', async () => {
|
|
71
|
+
expect(typeof globalThis.AbortSignal).toBe('function');
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
await it('should create controller with signal', async () => {
|
|
75
|
+
const ac = new AbortController();
|
|
76
|
+
expect(ac.signal).toBeDefined();
|
|
77
|
+
expect(ac.signal.aborted).toBe(false);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
await it('abort() should set signal.aborted to true', async () => {
|
|
81
|
+
const ac = new AbortController();
|
|
82
|
+
ac.abort();
|
|
83
|
+
expect(ac.signal.aborted).toBe(true);
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
// ==================== Web Streams ====================
|
|
88
|
+
await describe('Web Streams', async () => {
|
|
89
|
+
await it('ReadableStream should be available as global', async () => {
|
|
90
|
+
expect(typeof globalThis.ReadableStream).toBe('function');
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
await it('WritableStream should be available as global', async () => {
|
|
94
|
+
expect(typeof globalThis.WritableStream).toBe('function');
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
await it('TransformStream should be available as global', async () => {
|
|
98
|
+
expect(typeof globalThis.TransformStream).toBe('function');
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
await it('ReadableStream should be constructable', async () => {
|
|
102
|
+
const rs = new ReadableStream({
|
|
103
|
+
start(controller) {
|
|
104
|
+
controller.enqueue('test');
|
|
105
|
+
controller.close();
|
|
106
|
+
},
|
|
107
|
+
});
|
|
108
|
+
expect(rs).toBeDefined();
|
|
109
|
+
const reader = rs.getReader();
|
|
110
|
+
const { value } = await reader.read();
|
|
111
|
+
expect(value).toBe('test');
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
await it('WritableStream should be constructable', async () => {
|
|
115
|
+
let received = '';
|
|
116
|
+
const ws = new WritableStream({
|
|
117
|
+
write(chunk) { received += chunk; },
|
|
118
|
+
});
|
|
119
|
+
const writer = ws.getWriter();
|
|
120
|
+
await writer.write('hello');
|
|
121
|
+
await writer.close();
|
|
122
|
+
expect(received).toBe('hello');
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
await it('TransformStream should be constructable', async () => {
|
|
126
|
+
const ts = new TransformStream({
|
|
127
|
+
transform(chunk, controller) {
|
|
128
|
+
controller.enqueue(String(chunk).toUpperCase());
|
|
129
|
+
},
|
|
130
|
+
});
|
|
131
|
+
expect(ts.readable).toBeDefined();
|
|
132
|
+
expect(ts.writable).toBeDefined();
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
// ==================== TextEncoderStream / TextDecoderStream ====================
|
|
137
|
+
await describe('Encoding Streams', async () => {
|
|
138
|
+
await it('TextEncoderStream should be available as global', async () => {
|
|
139
|
+
expect(typeof globalThis.TextEncoderStream).toBe('function');
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
await it('TextDecoderStream should be available as global', async () => {
|
|
143
|
+
expect(typeof globalThis.TextDecoderStream).toBe('function');
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
// ==================== Compression Streams ====================
|
|
148
|
+
await describe('Compression Streams', async () => {
|
|
149
|
+
await it('CompressionStream should be available as global', async () => {
|
|
150
|
+
expect(typeof globalThis.CompressionStream).toBe('function');
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
await it('DecompressionStream should be available as global', async () => {
|
|
154
|
+
expect(typeof globalThis.DecompressionStream).toBe('function');
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
// ==================== WebCrypto ====================
|
|
159
|
+
await describe('WebCrypto', async () => {
|
|
160
|
+
await it('crypto should be available as global', async () => {
|
|
161
|
+
expect(typeof globalThis.crypto).toBe('object');
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
await it('crypto.subtle should be available', async () => {
|
|
165
|
+
expect(globalThis.crypto.subtle).toBeDefined();
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
await it('crypto.getRandomValues should work', async () => {
|
|
169
|
+
const buf = new Uint8Array(16);
|
|
170
|
+
crypto.getRandomValues(buf);
|
|
171
|
+
// At least one byte should be non-zero (statistically almost certain)
|
|
172
|
+
expect(buf.some(b => b !== 0)).toBe(true);
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
await it('crypto.randomUUID should return a UUID string', async () => {
|
|
176
|
+
const uuid = crypto.randomUUID();
|
|
177
|
+
expect(typeof uuid).toBe('string');
|
|
178
|
+
expect(uuid.length).toBe(36);
|
|
179
|
+
expect(uuid[8]).toBe('-');
|
|
180
|
+
expect(uuid[13]).toBe('-');
|
|
181
|
+
});
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
// ==================== EventSource ====================
|
|
185
|
+
await describe('EventSource', async () => {
|
|
186
|
+
await it('EventSource should be available as global', async () => {
|
|
187
|
+
expect(typeof globalThis.EventSource).toBe('function');
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
await it('EventSource should have readyState constants', async () => {
|
|
191
|
+
expect(EventSource.CONNECTING).toBe(0);
|
|
192
|
+
expect(EventSource.OPEN).toBe(1);
|
|
193
|
+
expect(EventSource.CLOSED).toBe(2);
|
|
194
|
+
});
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
// ==================== URL / URLSearchParams ====================
|
|
198
|
+
await describe('URL', async () => {
|
|
199
|
+
await it('URL should be available as global', async () => {
|
|
200
|
+
expect(typeof globalThis.URL).toBe('function');
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
await it('should parse URLs correctly', async () => {
|
|
204
|
+
const u = new URL('https://example.com:8080/path?q=1#hash');
|
|
205
|
+
expect(u.hostname).toBe('example.com');
|
|
206
|
+
expect(u.port).toBe('8080');
|
|
207
|
+
expect(u.pathname).toBe('/path');
|
|
208
|
+
expect(u.search).toBe('?q=1');
|
|
209
|
+
expect(u.hash).toBe('#hash');
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
await it('URLSearchParams should be available as global', async () => {
|
|
213
|
+
expect(typeof globalThis.URLSearchParams).toBe('function');
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
await it('URLSearchParams should work', async () => {
|
|
217
|
+
const params = new URLSearchParams('a=1&b=2');
|
|
218
|
+
expect(params.get('a')).toBe('1');
|
|
219
|
+
expect(params.get('b')).toBe('2');
|
|
220
|
+
});
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
// ==================== Blob / File ====================
|
|
224
|
+
await describe('Blob', async () => {
|
|
225
|
+
await it('Blob should be available as global', async () => {
|
|
226
|
+
expect(typeof globalThis.Blob).toBe('function');
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
await it('should create Blob with correct size', async () => {
|
|
230
|
+
const blob = new Blob(['hello']);
|
|
231
|
+
expect(blob.size).toBe(5);
|
|
232
|
+
expect(blob.type).toBe('');
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
await it('should support type option', async () => {
|
|
236
|
+
const blob = new Blob(['{}'], { type: 'application/json' });
|
|
237
|
+
expect(blob.type).toBe('application/json');
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
await it('File should be available as global', async () => {
|
|
241
|
+
expect(typeof (globalThis as any).File).toBe('function');
|
|
242
|
+
});
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
// ==================== FormData ====================
|
|
246
|
+
await describe('FormData', async () => {
|
|
247
|
+
await it('FormData should be available as global', async () => {
|
|
248
|
+
expect(typeof globalThis.FormData).toBe('function');
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
await it('should support append and get', async () => {
|
|
252
|
+
const fd = new FormData();
|
|
253
|
+
fd.append('key', 'value');
|
|
254
|
+
expect(fd.get('key')).toBe('value');
|
|
255
|
+
});
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
// ==================== Performance ====================
|
|
259
|
+
await describe('Performance', async () => {
|
|
260
|
+
await it('performance should be available as global', async () => {
|
|
261
|
+
expect(globalThis.performance).toBeDefined();
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
await it('performance.now() should return a number', async () => {
|
|
265
|
+
const t = performance.now();
|
|
266
|
+
expect(typeof t).toBe('number');
|
|
267
|
+
expect(t).toBeGreaterThan(0);
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
await it('performance.timeOrigin should be a number', async () => {
|
|
271
|
+
expect(typeof performance.timeOrigin).toBe('number');
|
|
272
|
+
expect(performance.timeOrigin).toBeGreaterThan(0);
|
|
273
|
+
});
|
|
274
|
+
});
|
|
275
|
+
});
|
|
276
|
+
};
|
package/src/index.ts
CHANGED
|
@@ -1,6 +1,69 @@
|
|
|
1
|
+
// Unified Web API globals for GJS
|
|
2
|
+
// Importing each package triggers its global registration (e.g. globalThis.Event = ...)
|
|
3
|
+
// On Node.js, these are no-ops since natives are already available.
|
|
4
|
+
|
|
5
|
+
// DOMException (WebIDL standard)
|
|
6
|
+
import '@gjsify/dom-exception';
|
|
7
|
+
|
|
8
|
+
// DOM Events: Event, EventTarget, CustomEvent
|
|
1
9
|
import '@gjsify/dom-events';
|
|
10
|
+
|
|
11
|
+
// AbortController, AbortSignal
|
|
2
12
|
import '@gjsify/abort-controller';
|
|
3
13
|
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
|
|
14
|
+
// WHATWG Streams: ReadableStream, WritableStream, TransformStream,
|
|
15
|
+
// TextEncoderStream, TextDecoderStream, queuing strategies
|
|
16
|
+
import '@gjsify/web-streams';
|
|
17
|
+
|
|
18
|
+
// CompressionStream, DecompressionStream
|
|
19
|
+
import '@gjsify/compression-streams';
|
|
20
|
+
|
|
21
|
+
// WebCrypto: crypto.subtle, getRandomValues, randomUUID
|
|
22
|
+
import '@gjsify/webcrypto';
|
|
23
|
+
|
|
24
|
+
// EventSource (Server-Sent Events)
|
|
25
|
+
import '@gjsify/eventsource';
|
|
26
|
+
|
|
27
|
+
// --- Newly consolidated globals ---
|
|
28
|
+
|
|
29
|
+
// URL, URLSearchParams (WHATWG URL Standard, GLib.Uri-based)
|
|
30
|
+
import { URL, URLSearchParams } from '@gjsify/url';
|
|
31
|
+
if (typeof globalThis.URL !== 'function') {
|
|
32
|
+
Object.defineProperty(globalThis, 'URL', { value: URL, writable: true, configurable: true });
|
|
33
|
+
}
|
|
34
|
+
if (typeof globalThis.URLSearchParams !== 'function') {
|
|
35
|
+
Object.defineProperty(globalThis, 'URLSearchParams', { value: URLSearchParams, writable: true, configurable: true });
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Blob, File (WHATWG File API)
|
|
39
|
+
import { Blob, File } from '@gjsify/buffer';
|
|
40
|
+
if (typeof globalThis.Blob !== 'function') {
|
|
41
|
+
Object.defineProperty(globalThis, 'Blob', { value: Blob, writable: true, configurable: true });
|
|
42
|
+
}
|
|
43
|
+
if (typeof (globalThis as any).File !== 'function') {
|
|
44
|
+
Object.defineProperty(globalThis, 'File', { value: File, writable: true, configurable: true });
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// FormData (WHATWG XMLHttpRequest Standard)
|
|
48
|
+
import { FormData } from '@gjsify/formdata';
|
|
49
|
+
if (typeof globalThis.FormData !== 'function') {
|
|
50
|
+
Object.defineProperty(globalThis, 'FormData', { value: FormData, writable: true, configurable: true });
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Performance (Web Performance API)
|
|
54
|
+
import { performance, PerformanceObserver } from '@gjsify/perf_hooks';
|
|
55
|
+
if (!globalThis.performance) {
|
|
56
|
+
Object.defineProperty(globalThis, 'performance', { value: performance, writable: true, configurable: true });
|
|
57
|
+
}
|
|
58
|
+
if (typeof (globalThis as any).PerformanceObserver !== 'function') {
|
|
59
|
+
Object.defineProperty(globalThis, 'PerformanceObserver', { value: PerformanceObserver, writable: true, configurable: true });
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Re-export key types for convenience
|
|
63
|
+
export { DOMException } from '@gjsify/dom-exception';
|
|
64
|
+
export { Event, EventTarget, CustomEvent } from '@gjsify/dom-events';
|
|
65
|
+
export { AbortController, AbortSignal } from '@gjsify/abort-controller';
|
|
66
|
+
export { URL, URLSearchParams } from '@gjsify/url';
|
|
67
|
+
export { Blob, File } from '@gjsify/buffer';
|
|
68
|
+
export { FormData } from '@gjsify/formdata';
|
|
69
|
+
export { performance, PerformanceObserver } from '@gjsify/perf_hooks';
|
package/src/test.mts
CHANGED
package/tsconfig.json
CHANGED
|
@@ -1,18 +1,31 @@
|
|
|
1
1
|
{
|
|
2
2
|
"compilerOptions": {
|
|
3
|
-
"module": "
|
|
4
|
-
"types": [
|
|
3
|
+
"module": "NodeNext",
|
|
4
|
+
"types": [
|
|
5
|
+
"node"
|
|
6
|
+
],
|
|
5
7
|
"target": "ESNext",
|
|
6
8
|
"moduleResolution": "NodeNext",
|
|
7
9
|
"experimentalDecorators": true,
|
|
10
|
+
"emitDeclarationOnly": true,
|
|
11
|
+
"declaration": true,
|
|
8
12
|
"outDir": "lib",
|
|
9
13
|
"rootDir": "src",
|
|
10
|
-
"
|
|
14
|
+
"declarationDir": "lib/types",
|
|
15
|
+
"composite": true,
|
|
16
|
+
"skipLibCheck": true,
|
|
17
|
+
"allowJs": true,
|
|
18
|
+
"checkJs": false,
|
|
19
|
+
"strict": false
|
|
11
20
|
},
|
|
12
|
-
"skipLibCheck": true,
|
|
13
|
-
"allowJs": true,
|
|
14
|
-
"checkJs": false,
|
|
15
21
|
"reflection": false,
|
|
16
|
-
"include": [
|
|
17
|
-
|
|
18
|
-
|
|
22
|
+
"include": [
|
|
23
|
+
"src/**/*.ts"
|
|
24
|
+
],
|
|
25
|
+
"exclude": [
|
|
26
|
+
"src/test.ts",
|
|
27
|
+
"src/test.mts",
|
|
28
|
+
"src/**/*.spec.ts",
|
|
29
|
+
"src/**/*.spec.mts"
|
|
30
|
+
]
|
|
31
|
+
}
|