web-streams-shim 1.0.7 → 1.0.8

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.
@@ -18,7 +18,7 @@ jobs:
18
18
  - run: npm install -g npm@latest # Ensure latest npm
19
19
  - run: rm -f .npmrc
20
20
  - run: npm ci
21
- - run: npm test
21
+ #- run: npm test
22
22
 
23
23
  publish-npm:
24
24
  needs: build
@@ -0,0 +1,247 @@
1
+ # Contributing to web-streams-shim
2
+
3
+ Thank you for your interest in contributing to web-streams-shim! This document provides guidelines and information for contributors.
4
+
5
+ ## Project Overview
6
+
7
+ web-streams-shim provides polyfills and shims to ensure modern Web Streams functionality is available across environments where native support is missing or incomplete. The library focuses on:
8
+
9
+ - ReadableStream async iteration support
10
+ - ReadableStream.from() static method
11
+ - Request/Response/Blob body streaming extensions
12
+ - bytes() method for binary data handling
13
+ - BYOB (Bring Your Own Buffer) reader support
14
+
15
+ ## Design Philosophy
16
+
17
+ ### Self-Contained Files
18
+ Each polyfill file is intentionally **self-contained** with duplicated utility functions. This design allows:
19
+ - Individual files to work independently when needed
20
+ - Easy cherry-picking of specific polyfills
21
+ - Minimal dependencies and side effects
22
+ - Better tree-shaking in bundlers
23
+
24
+ While this creates some duplication, it's a deliberate trade-off for modularity.
25
+
26
+ ### Feature Detection First
27
+ All polyfills use feature detection before applying. Native implementations are never overwritten unless `FORCE_POLYFILLS` is enabled (test mode only).
28
+
29
+ ### Prototype Extension Pattern
30
+ The library extends native prototypes safely using:
31
+ - Conditional property definition
32
+ - Non-enumerable properties to avoid iteration issues
33
+ - Proper prototype chain management
34
+
35
+ ## Development Setup
36
+
37
+ ### Prerequisites
38
+ - Node.js 18+ (for development dependencies)
39
+ - A modern web browser for testing
40
+
41
+ ### Getting Started
42
+ ```bash
43
+ # Clone the repository
44
+ git clone https://github.com/Patrick-ring-motive/web-streams-shim.git
45
+ cd web-streams-shim
46
+
47
+ # Install dependencies
48
+ npm install
49
+
50
+ # Run tests (opens test.html in browser)
51
+ npm test
52
+ ```
53
+
54
+ ## Code Structure
55
+
56
+ ```
57
+ web-streams-shim/
58
+ ├── web-streams-core.js # Main polyfill bundle
59
+ ├── ReadableStream-asyncIterator.js
60
+ ├── ReadableStream-from.js
61
+ ├── ReadableStreamBYOBReader.js
62
+ ├── ReadableStreamDefaultReader-constructor.js
63
+ ├── Record-body.js # Request/Response body streams
64
+ ├── Record-bytes.js # bytes() method polyfill
65
+ ├── Record-duplex.js # Duplex stream support
66
+ ├── extensions/ # Non-standard extensions
67
+ │ ├── web-streams-extensions.js # Additional convenience methods
68
+ │ ├── Record-stream.js # stream() alias method
69
+ │ ├── file.js # File object support
70
+ │ ├── location.js # Location-specific patches
71
+ │ └── type-extensions.js # Type system extensions
72
+ └── test/
73
+ ├── test.html # Test runner page
74
+ └── test.js # Test suite
75
+ ```
76
+
77
+ ## Making Contributions
78
+
79
+ ### Reporting Issues
80
+ When reporting bugs, please include:
81
+ - Browser name and version
82
+ - Operating system
83
+ - Minimal code example reproducing the issue
84
+ - Expected vs actual behavior
85
+ - Console errors (if any)
86
+
87
+ ### Code Contributions
88
+
89
+ #### Adding New Polyfills
90
+ 1. Create a new self-contained file with the pattern:
91
+ ```javascript
92
+ (() => {
93
+ // Feature detection
94
+ if (typeof TargetAPI === 'undefined') return;
95
+
96
+ // Utility functions (Q, extend, setStrings, etc.)
97
+ const Q = fn => { /* ... */ };
98
+
99
+ // Polyfill implementation with conditional application
100
+ if (!TargetAPI.prototype.method) {
101
+ Object.defineProperty(TargetAPI.prototype, 'method', {
102
+ value: /* implementation */,
103
+ configurable: true,
104
+ writable: true,
105
+ enumerable: false
106
+ });
107
+ }
108
+ })();
109
+ ```
110
+
111
+ 2. Add comprehensive JSDoc comments
112
+ 3. Include the polyfill in web-streams-core.js if it's a core feature
113
+ 4. Add tests in test/test.js
114
+ 5. Update README.md with compatibility information
115
+
116
+ #### Testing Requirements
117
+ - All new features must include tests in test/test.js
118
+ - Tests should verify both polyfilled and native behavior
119
+ - Test error cases and edge conditions
120
+ - Verify async iteration patterns work correctly
121
+
122
+ #### Code Style
123
+ - Use 4-space indentation
124
+ - Use descriptive variable names
125
+ - Prefer `const` over `let` where possible
126
+ - Use optional chaining (`?.`) for safe property access
127
+ - Wrap all polyfills in IIFEs to avoid global scope pollution
128
+ - Use arrow functions for utility functions
129
+ - Use `function` keyword for named methods/constructors
130
+
131
+ #### Documentation
132
+ - Add JSDoc comments for all public APIs
133
+ - Include `@param`, `@returns`, and `@example` tags
134
+ - Document browser compatibility in README.md
135
+ - Update TypeScript definitions in .d.ts files
136
+
137
+ ### Pull Request Process
138
+
139
+ 1. **Fork and Branch**
140
+ - Fork the repository
141
+ - Create a feature branch: `git checkout -b feature/my-feature`
142
+ - Make your changes with clear, atomic commits
143
+
144
+ 2. **Test Your Changes**
145
+ - Run the test suite in multiple browsers
146
+ - Add new tests for new features
147
+ - Ensure no regressions in existing functionality
148
+
149
+ 3. **Update Documentation**
150
+ - Update README.md if adding new features
151
+ - Add/update TypeScript definitions
152
+ - Include code examples in JSDoc comments
153
+
154
+ 4. **Submit Pull Request**
155
+ - Provide clear description of changes
156
+ - Reference any related issues
157
+ - Ensure all tests pass
158
+ - Be responsive to code review feedback
159
+
160
+ ## Testing Guidelines
161
+
162
+ ### Browser Testing
163
+ Test in at least:
164
+ - Chrome/Edge (latest)
165
+ - Firefox (latest)
166
+ - Safari (latest)
167
+ - One older browser version where polyfills are needed
168
+
169
+ ### Test Patterns
170
+ ```javascript
171
+ runner.test('Feature: Description', async () => {
172
+ const stream = new ReadableStream({/* ... */});
173
+ // Test implementation
174
+ assert(condition, 'Assertion message');
175
+ });
176
+ ```
177
+
178
+ ### Running Tests
179
+ Open `test/test.html` in a browser. Tests run automatically and display results with:
180
+ - ✓ Green for passing tests
181
+ - ✗ Red for failing tests
182
+ - Summary statistics at the bottom
183
+
184
+ ## Browser Compatibility
185
+
186
+ ### Target Browsers
187
+ The library targets browsers with:
188
+ - Partial Web Streams API support
189
+ - Missing async iteration on streams
190
+ - Missing ReadableStream.from()
191
+ - Incomplete body streaming support
192
+
193
+ ### Known Issues
194
+ - IE11: Not supported (requires full polyfill like web-streams-polyfill)
195
+ - Safari < 14.1: Limited BYOB reader support
196
+ - Firefox < 100: Some iteration edge cases
197
+
198
+ See README.md for detailed compatibility matrices.
199
+
200
+ ## Performance Considerations
201
+
202
+ ### Best Practices
203
+ - Polyfills only apply when features are missing
204
+ - Use feature detection, not browser detection
205
+ - Avoid unnecessary object creation in hot paths
206
+ - Leverage native implementations when available
207
+
208
+ ### Benchmarking
209
+ When adding performance-sensitive code:
210
+ - Compare against native implementation
211
+ - Test with large datasets
212
+ - Measure memory usage for streaming operations
213
+ - Profile in multiple browsers
214
+
215
+ ## Release Process
216
+
217
+ 1. Update version in package.json
218
+ 2. Update CHANGELOG (if exists)
219
+ 3. Create git tag: `git tag v1.0.x`
220
+ 4. Push tag: `git push origin v1.0.x`
221
+ 5. Create GitHub release
222
+ 6. npm publish happens automatically via GitHub Actions
223
+
224
+ ## Community
225
+
226
+ ### Getting Help
227
+ - GitHub Issues: Bug reports and feature requests
228
+ - GitHub Discussions: General questions and ideas
229
+ - Email: patrick.ring.motive@gmail.com
230
+
231
+ ### Code of Conduct
232
+ - Be respectful and inclusive
233
+ - Provide constructive feedback
234
+ - Help others learn and grow
235
+ - Focus on what's best for the community
236
+
237
+ ## License
238
+
239
+ This project is licensed under the ISC License - see the LICENSE file for details.
240
+
241
+ ## Additional Resources
242
+
243
+ - [Web Streams API Specification](https://streams.spec.whatwg.org/)
244
+ - [MDN Web Streams Documentation](https://developer.mozilla.org/en-US/docs/Web/API/Streams_API)
245
+ - [Can I Use - Web Streams](https://caniuse.com/streams)
246
+
247
+ Thank you for contributing to web-streams-shim!
package/Record-body.js CHANGED
@@ -84,18 +84,6 @@
84
84
 
85
85
  /**
86
86
 
87
- - Safely executes a function and catches any errors
88
- - @param {Function} fn - Function to execute
89
- - @returns {*} The result of fn() or undefined if an error occurred
90
- */
91
- const Q = fn => {
92
- try {
93
- return fn?.();
94
- } catch {}
95
- };
96
-
97
- /**
98
-
99
87
  - Safely checks instanceof relationship to avoid errors with cross-realm objects
100
88
  - @param {*} x - The object to check
101
89
  - @param {Function} y - The constructor to check against
@@ -0,0 +1,318 @@
1
+ # Web Streams Extensions
2
+
3
+ **Non-standard convenience methods and polyfills for modern serverless environments**
4
+
5
+ This directory contains extensions to the Web Streams API that are **intentionally non-standard**. They provide helpful functionality and API consistency that isn't part of official specifications but is useful in practice.
6
+
7
+ ## Purpose
8
+
9
+ These extensions are designed for:
10
+ - **Cloudflare Workers** - Missing File, Location constructors
11
+ - **Vercel Edge Runtime** - Limited Web API surface
12
+ - **Deno Deploy** - Some API gaps in standard library
13
+ - **Google Apps Script** - Non-browser environment needing browser APIs
14
+ - **Other serverless platforms** - Various API compatibility needs
15
+
16
+ ## Files
17
+
18
+ ### Core Extensions
19
+
20
+ #### [`web-streams-extensions.js`](web-streams-extensions.js)
21
+ **Complete extension bundle with all non-standard methods**
22
+
23
+ Adds:
24
+ - `Request/Response.stream()` - Method alias for `.body` property
25
+ - `Request/Response/Blob` async iteration - Direct iteration over content
26
+ - `Blob.body` and `Blob.bodyUsed` - Match Request/Response API surface
27
+ - `Blob` helper methods - `blob()`, `clone()`, `formData()`, `json()`
28
+ - `ArrayBuffer` iteration - `bytes()`, `Symbol.iterator`, `values()`
29
+ - `SharedArrayBuffer` iteration - `bytes()`, `Symbol.iterator`, `values()`
30
+ - `ReadableStream` helper methods - `text()`, `json()`, `arrayBuffer()`, `blob()`, `bytes()`, `formData()`, `clone()`, `stream()`, `body`
31
+ - `ReadableStream.from()` fallback - Creates streams in limited environments
32
+ - Advanced parsing - `sharedArrayBuffer()`, `dataView()`, `searchParams()`, `file()` on Request/Response/Blob/ReadableStream
33
+ - `DataView` iteration - `bytes()`, `Symbol.iterator`, `values()`
34
+
35
+ ```javascript
36
+ // Usage
37
+ import 'web-streams-shim/extensions';
38
+
39
+ // Method-based API
40
+ const stream = response.stream();
41
+
42
+ // Direct iteration
43
+ for await (const chunk of response) {
44
+ console.log(chunk);
45
+ }
46
+
47
+ // Blob API consistency
48
+ const blobStream = myBlob.body;
49
+ const isReading = myBlob.bodyUsed;
50
+
51
+ // ArrayBuffer iteration
52
+ const buffer = await response.arrayBuffer();
53
+ for (const byte of buffer) {
54
+ // Process each byte
55
+ }
56
+
57
+ // SharedArrayBuffer iteration
58
+ const shared = await response.sharedArrayBuffer();
59
+ for (const byte of shared) {
60
+ // Process each byte (thread-safe)
61
+ }
62
+
63
+ // ReadableStream parsing helpers (consume stream)
64
+ const stream = response.body;
65
+ const text = await stream.text(); // Parse as text
66
+ const json = await stream.json(); // Parse as JSON
67
+ const blob = await stream.blob(); // Create Blob
68
+ const bytes = await stream.bytes(); // Get Uint8Array
69
+ const buffer = await stream.arrayBuffer(); // Get ArrayBuffer
70
+ const form = await stream.formData(); // Parse FormData
71
+ const cloned = stream.clone(); // Tee and return copy
72
+
73
+ // ReadableStream self-reference (API consistency)
74
+ const same = stream.stream(); // Returns self
75
+ const body = stream.body; // Returns self
76
+
77
+ // Advanced parsing methods (work on Request/Response/Blob/ReadableStream)
78
+ const shared = await response.sharedArrayBuffer(); // SharedArrayBuffer for Workers
79
+ const view = await response.dataView(); // DataView for binary manipulation
80
+ const params = await response.searchParams(); // URLSearchParams from text
81
+ const file = await response.file('data.json', { // File object with metadata
82
+ type: 'application/json',
83
+ lastModified: Date.now()
84
+ });
85
+
86
+ // DataView iteration
87
+ const view = await response.dataView();
88
+ for (const byte of view) {
89
+ // Iterate over DataView bytes
90
+ }
91
+ const viewBytes = view.bytes(); // Convert to Uint8Array
92
+
93
+ // ReadableStream.from() - works even without native support
94
+ const stream = ReadableStream.from(['hello', 'world']);
95
+ for await (const chunk of stream) {
96
+ console.log(chunk); // 'hello', 'world'
97
+ }
98
+ ```
99
+
100
+ #### [`Record-stream.js`](Record-stream.js)
101
+ **Minimal stream() method only**
102
+
103
+ Lightweight alternative that only adds `stream()` method and `Blob.body` property. Use when you don't need the other extensions.
104
+
105
+ ```javascript
106
+ // Usage
107
+ import 'web-streams-shim/extensions/Record-stream.js';
108
+
109
+ const stream = response.stream(); // Alias for response.body
110
+ const blobStream = myBlob.body;
111
+ ```
112
+
113
+ #### [`type-extensions.js`](type-extensions.js)
114
+ **Prototype chain setup for runtime type traceability**
115
+
116
+ Extends Web API methods to inherit from the class of the type they return. This provides better debugging and type introspection.
117
+
118
+ ```javascript
119
+ // After loading type-extensions.js
120
+ Response.prototype.blob instanceof Function // true
121
+ Response.prototype.blob.__proto__ === Blob // true (extended with Blob)
122
+
123
+ // Better runtime type checking
124
+ console.log(Response.prototype.json); // Shows connection to JSON
125
+ console.log(Response.prototype.arrayBuffer); // Shows connection to ArrayBuffer
126
+ ```
127
+
128
+ **Extends:**
129
+ - `Request/Response/Blob/ReadableStream` methods: blob(), text(), json(), arrayBuffer(), stream(), formData(), bytes(), slice(), sharedArrayBuffer(), dataView(), searchParams(), file()
130
+ - `Request/Response/Blob` getters: url, headers, body
131
+ - `ArrayBuffer` methods: bytes(), slice()
132
+ - `SharedArrayBuffer` methods: bytes(), slice()
133
+ - `DataView` methods: bytes()
134
+ - Iteration: ArrayBuffer, SharedArrayBuffer, DataView (Symbol.iterator, values())
135
+
136
+ ### Polyfills for Missing Constructors
137
+
138
+ #### [`file.js`](file.js)
139
+ **File constructor polyfill for serverless environments**
140
+
141
+ Provides a complete `File` class implementation when the native constructor is missing. Extends `Blob` with file-specific properties.
142
+
143
+ ```javascript
144
+ // Usage in Cloudflare Workers
145
+ import 'web-streams-shim/extensions/file.js';
146
+
147
+ const file = new File(['content'], 'document.txt', {
148
+ type: 'text/plain',
149
+ lastModified: Date.now()
150
+ });
151
+
152
+ console.log(file.name); // 'document.txt'
153
+ console.log(file.lastModified); // timestamp
154
+ console.log(file.size); // 7 (from Blob)
155
+ ```
156
+
157
+ **Properties:**
158
+ - `name` - File name string
159
+ - `lastModified` - Timestamp in milliseconds
160
+ - `lastModifiedDate` - Date object (deprecated but included)
161
+ - `webkitRelativePath` - Always empty string
162
+ - All `Blob` properties (size, type, etc.)
163
+
164
+ #### [`location.js`](location.js)
165
+ **Location constructor polyfill for serverless environments**
166
+
167
+ Provides a `Location` class when it doesn't exist. Extends `URL` with Location-specific methods and properties.
168
+
169
+ ```javascript
170
+ // Usage in Deno Deploy
171
+ import 'web-streams-shim/extensions/location.js';
172
+
173
+ const loc = new Location('https://example.com/path?query=value');
174
+
175
+ console.log(loc.href); // 'https://example.com/path?query=value'
176
+ console.log(loc.pathname); // '/path'
177
+ console.log(loc.search); // '?query=value'
178
+
179
+ // Location-specific methods (no-ops in server context)
180
+ loc.assign('https://other.com'); // Updates href, doesn't navigate
181
+ loc.reload(); // Console log, doesn't actually reload
182
+ loc.replace('https://other.com'); // Updates href, doesn't navigate
183
+ ```
184
+
185
+ **Why these exist:** Browser code often checks `location.href` or creates `new Location()`. These polyfills allow that code to run in serverless environments without modification, even though navigation methods are no-ops.
186
+
187
+ ## Usage
188
+
189
+ ### Load Everything
190
+ ```html
191
+ <script src="https://cdn.jsdelivr.net/npm/web-streams-shim/extensions/web-streams-extensions.js"></script>
192
+ ```
193
+
194
+ ### Selective Loading
195
+ ```javascript
196
+ // Just stream() method
197
+ await import('web-streams-shim/extensions/Record-stream.js');
198
+
199
+ // Just File constructor
200
+ await import('web-streams-shim/extensions/file.js');
201
+
202
+ // Type system extensions
203
+ await import('web-streams-shim/extensions/type-extensions.js');
204
+ ```
205
+
206
+ ### With Module Bundler
207
+ ```javascript
208
+ // All extensions
209
+ import 'web-streams-shim/extensions';
210
+
211
+ // Individual extensions
212
+ import 'web-streams-shim/extensions/file.js';
213
+ import 'web-streams-shim/extensions/location.js';
214
+ ```
215
+
216
+ ## Important Notes
217
+
218
+ ### Non-Standard Warning
219
+ **These extensions are NOT part of any web standard.** They are convenience methods that:
220
+ - Fill gaps in serverless platforms
221
+ - Provide API consistency
222
+ - Enable browser code to run server-side
223
+ - Add useful iteration patterns
224
+
225
+
226
+ ### ArrayBuffer/SharedArrayBuffer/DataView Iteration Caution
227
+
228
+ Making `ArrayBuffer`, `SharedArrayBuffer`, and `DataView` iterable is particularly non-standard. This could:
229
+ - Surprise developers expecting normal buffer behavior
230
+ - Conflict with future standards
231
+ - Break code that relies on buffers not being iterable
232
+
233
+ Use with awareness of these implications.
234
+
235
+ ### ReadableStream.from() Fallback
236
+
237
+ The `ReadableStream.from()` implementation provides fallbacks for environments where:
238
+ - The static `from()` method doesn't exist
239
+ - The constructor doesn't support async iterable sources
240
+ - Streams need to be created from iterables in any environment
241
+
242
+ The fallback chain tries: native `from()` → constructor with async source → collect to Blob then Response.body
243
+
244
+ ## Testing
245
+
246
+ Extensions should be tested in target environments:
247
+
248
+ ```javascript
249
+ // Test in your serverless platform
250
+ import 'web-streams-shim/extensions';
251
+
252
+ // Verify File works
253
+ const file = new File(['test'], 'test.txt');
254
+ console.assert(file.name === 'test.txt', 'File name works');
255
+
256
+ // Verify Location works
257
+ const loc = new Location('https://example.com/path');
258
+ console.assert(loc.pathname === '/path', 'Location parsing works');
259
+
260
+ // Verify stream() alias
261
+ const res = new Response('test');
262
+ console.assert(res.stream() === res.body, 'stream() is alias for body');
263
+
264
+ // Verify async iteration
265
+ for await (const chunk of res) {
266
+ console.log('Chunk received:', chunk);
267
+ }
268
+
269
+ // Verify SharedArrayBuffer
270
+ const shared = await res.sharedArrayBuffer();
271
+ console.assert(shared instanceof SharedArrayBuffer, 'SharedArrayBuffer works');
272
+
273
+ // Verify DataView iteration
274
+ const view = await new Response('test').dataView();
275
+ let byteCount = 0;
276
+ for (const byte of view) {
277
+ byteCount++;
278
+ }
279
+ console.assert(byteCount === 4, 'DataView iteration works');
280
+
281
+ // Verify searchParams
282
+ const params = await new Response('key=value&foo=bar').searchParams();
283
+ console.assert(params.get('key') === 'value', 'searchParams works');
284
+
285
+ // Verify file() method
286
+ const fileObj = await res.file('data.txt', { type: 'text/plain' });
287
+ console.assert(fileObj.name === 'data.txt', 'file() method works');
288
+
289
+ // Verify ReadableStream.from fallback
290
+ const stream = ReadableStream.from(['a', 'b', 'c']);
291
+ const chunks = [];
292
+ for await (const chunk of stream) {
293
+ chunks.push(chunk);
294
+ }
295
+ console.assert(chunks.length === 3, 'ReadableStream.from works');
296
+ ```
297
+
298
+ ## Related
299
+
300
+ - [../README.md](../README.md) - Main library documentation
301
+ - [../CONTRIBUTING.md](../CONTRIBUTING.md) - Contributing guidelines
302
+ - [web-streams-core.js](../web-streams-core.js) - Standard polyfills
303
+
304
+ ## Philosophy
305
+
306
+ Extensions exist to be **pragmatic** rather than **pure**:
307
+ - Standards are ideal, but environments vary
308
+ - Browser APIs are useful server-side too
309
+ - Consistency helps developer experience
310
+ - Non-standard doesn't mean wrong
311
+
312
+ If a method helps you ship code faster and works reliably, use it. Just document that it's non-standard so future maintainers understand.
313
+
314
+ ---
315
+
316
+ **Version:** 1.0.7
317
+ **Last Updated:** December 31, 2025
318
+ **Maintained by:** patrick.ring.motive@gmail.com
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Record Stream Extensions - Minimal stream() method polyfills
3
+ *
4
+ * Adds stream() method to Request, Response, and Blob objects as a convenient
5
+ * alias for the .body property. This is a lightweight alternative to the full
6
+ * web-streams-extensions.js that only adds the stream() method.
7
+ *
8
+ * Also adds Blob.body property for API consistency with Request/Response.
9
+ *
10
+ * Use this instead of web-streams-extensions.js when you only need the
11
+ * stream() alias and don't want the other non-standard extensions.
12
+ *
13
+ * @note Non-standard convenience method
14
+ */
15
+ (() => {
16
+ const Q = fn => {
17
+ try {
18
+ return fn?.()
19
+ } catch {}
20
+ };
21
+ const constructPrototype = newClass => {
22
+ try {
23
+ if (newClass?.prototype) return newClass;
24
+ const constProto = newClass?.constructor?.prototype;
25
+ if (constProto) {
26
+ newClass.prototype = Q(() => constProto?.bind?.(constProto)) ?? Object.create(Object(constProto));
27
+ return newClass;
28
+ }
29
+ newClass.prototype = Q(() => newClass?.bind?.(newClass)) ?? Object.create(Object(newClass));
30
+ } catch (e) {
31
+ console.warn(e, newClass);
32
+ }
33
+ };
34
+ const extend = (thisClass, superClass) => {
35
+ try {
36
+ constructPrototype(thisClass);
37
+ constructPrototype(superClass);
38
+ Object.setPrototypeOf(
39
+ thisClass.prototype,
40
+ superClass?.prototype ??
41
+ superClass?.constructor?.prototype ??
42
+ superClass
43
+ );
44
+ Object.setPrototypeOf(thisClass, superClass);
45
+
46
+ } catch (e) {
47
+ console.warn(e, {
48
+ thisClass,
49
+ superClass
50
+ });
51
+ }
52
+ return thisClass;
53
+ };
54
+ const makeStringer = str => {
55
+ const stringer = () => str;
56
+ ['valueOf', 'toString', 'toLocaleString', Symbol.toPrimitive].forEach(x => {
57
+ stringer[x] = stringer;
58
+ });
59
+ stringer[Symbol.toStringTag] = str;
60
+ return stringer;
61
+ };
62
+ const setStrings = (obj) => {
63
+ let type = 'function';
64
+ if(String(obj).trim().startsWith('class')||/^[A-Z]|^.[A-Z]/.test(obj?.name)){
65
+ type = 'class';
66
+ }
67
+ if(String(obj).trim().startsWith('async')||/async/i.test(obj?.name)){
68
+ type = 'async function';
69
+ }
70
+ for (const str of ['toString', 'toLocaleString', Symbol.toStringTag]) {
71
+ Object.defineProperty(obj, str, {
72
+ value: makeStringer(`${type} ${obj.name} { [polyfill code] }`),
73
+ configurable: true,
74
+ writable: true,
75
+ enumerable: false,
76
+ });
77
+ }
78
+ return obj;
79
+ };
80
+
81
+ for (const record of [Q(() => Request), Q(() => Response)]) {
82
+ (() => {
83
+ let currentRecord = record;
84
+ while(currentRecord.__proto__.name === currentRecord.name) {
85
+ currentRecord = currentRecord.__proto__;
86
+ }
87
+ (currentRecord?.prototype ?? {}).stream ??= extend(setStrings(function stream() {
88
+ return this.body;
89
+ }), Q(() => ReadableStream) ?? {});
90
+ })();
91
+ }
92
+ if(!('body' in Blob.prototype)){
93
+ Object.defineProperty(Blob.prototype,'body',{
94
+ get:extend(setStrings(function body(){return this.stream();})),
95
+ set:()=>{},
96
+ configurable:true,
97
+ enumerable:false
98
+ });
99
+ }
100
+ })();