quickjs 0.11.1 → 0.12.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.
- checksums.yaml +4 -4
- data/CLAUDE.md +62 -0
- data/README.md +7 -1
- data/Rakefile +53 -1
- data/ext/quickjsrb/extconf.rb +7 -1
- data/ext/quickjsrb/quickjsrb.c +28 -7
- data/ext/quickjsrb/quickjsrb.h +18 -2
- data/ext/quickjsrb/vendor/polyfill-file.min.js +1 -0
- data/ext/quickjsrb/vendor/polyfill-intl-en.min.js +10 -9
- data/lib/quickjs/version.rb +1 -1
- data/polyfills/package-lock.json +465 -0
- data/polyfills/package.json +18 -0
- data/polyfills/rolldown.config.mjs +20 -0
- data/polyfills/src/file.js +218 -0
- data/polyfills/src/intl-en.js +15 -0
- metadata +10 -6
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
// W3C Blob and File polyfill for QuickJS
|
|
2
|
+
// Spec: https://www.w3.org/TR/FileAPI/
|
|
3
|
+
|
|
4
|
+
class Blob {
|
|
5
|
+
#bytes;
|
|
6
|
+
#type;
|
|
7
|
+
|
|
8
|
+
constructor(blobParts, options) {
|
|
9
|
+
this.#type = normalizeType(options?.type ?? "");
|
|
10
|
+
|
|
11
|
+
if (!blobParts) {
|
|
12
|
+
this.#bytes = new Uint8Array(0);
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
if (!Array.isArray(blobParts)) {
|
|
17
|
+
throw new TypeError(
|
|
18
|
+
"Failed to construct 'Blob': The provided value cannot be converted to a sequence."
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const parts = [];
|
|
23
|
+
let totalLength = 0;
|
|
24
|
+
|
|
25
|
+
for (const part of blobParts) {
|
|
26
|
+
let bytes;
|
|
27
|
+
if (typeof part === "string") {
|
|
28
|
+
bytes = encodeUTF8(part);
|
|
29
|
+
} else if (part instanceof ArrayBuffer) {
|
|
30
|
+
bytes = new Uint8Array(part);
|
|
31
|
+
} else if (ArrayBuffer.isView(part)) {
|
|
32
|
+
bytes = new Uint8Array(part.buffer, part.byteOffset, part.byteLength);
|
|
33
|
+
} else if (part instanceof Blob) {
|
|
34
|
+
bytes = part.#bytes;
|
|
35
|
+
} else {
|
|
36
|
+
bytes = encodeUTF8(String(part));
|
|
37
|
+
}
|
|
38
|
+
parts.push(bytes);
|
|
39
|
+
totalLength += bytes.byteLength;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const merged = new Uint8Array(totalLength);
|
|
43
|
+
let offset = 0;
|
|
44
|
+
for (const part of parts) {
|
|
45
|
+
merged.set(part, offset);
|
|
46
|
+
offset += part.byteLength;
|
|
47
|
+
}
|
|
48
|
+
this.#bytes = merged;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
get size() {
|
|
52
|
+
return this.#bytes.byteLength;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
get type() {
|
|
56
|
+
return this.#type;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
slice(start, end, contentType) {
|
|
60
|
+
const size = this.size;
|
|
61
|
+
let relStart = start === undefined ? 0 : clampIndex(start, size);
|
|
62
|
+
let relEnd = end === undefined ? size : clampIndex(end, size);
|
|
63
|
+
const span = Math.max(relEnd - relStart, 0);
|
|
64
|
+
|
|
65
|
+
const sliced = new Blob();
|
|
66
|
+
sliced.#bytes = this.#bytes.slice(relStart, relStart + span);
|
|
67
|
+
sliced.#type = normalizeType(contentType ?? "");
|
|
68
|
+
return sliced;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
text() {
|
|
72
|
+
return Promise.resolve(decodeUTF8(this.#bytes));
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
arrayBuffer() {
|
|
76
|
+
return Promise.resolve(this.#bytes.buffer.slice(this.#bytes.byteOffset, this.#bytes.byteOffset + this.#bytes.byteLength));
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
toString() {
|
|
80
|
+
return "[object Blob]";
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
get [Symbol.toStringTag]() {
|
|
84
|
+
return "Blob";
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function normalizeType(type) {
|
|
89
|
+
// Spec: type must be lowercase ASCII without 0x20-7E exclusions
|
|
90
|
+
if (/[^\x20-\x7E]/.test(type)) {
|
|
91
|
+
return "";
|
|
92
|
+
}
|
|
93
|
+
return type.toLowerCase();
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function clampIndex(index, size) {
|
|
97
|
+
if (index < 0) {
|
|
98
|
+
return Math.max(size + index, 0);
|
|
99
|
+
}
|
|
100
|
+
return Math.min(index, size);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function encodeUTF8(str) {
|
|
104
|
+
// Manual UTF-8 encoding for QuickJS (no TextEncoder)
|
|
105
|
+
const utf8 = [];
|
|
106
|
+
for (let i = 0; i < str.length; i++) {
|
|
107
|
+
let code = str.charCodeAt(i);
|
|
108
|
+
|
|
109
|
+
// Handle surrogate pairs
|
|
110
|
+
if (code >= 0xd800 && code <= 0xdbff && i + 1 < str.length) {
|
|
111
|
+
const next = str.charCodeAt(i + 1);
|
|
112
|
+
if (next >= 0xdc00 && next <= 0xdfff) {
|
|
113
|
+
code = (code - 0xd800) * 0x400 + (next - 0xdc00) + 0x10000;
|
|
114
|
+
i++;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (code <= 0x7f) {
|
|
119
|
+
utf8.push(code);
|
|
120
|
+
} else if (code <= 0x7ff) {
|
|
121
|
+
utf8.push(0xc0 | (code >> 6), 0x80 | (code & 0x3f));
|
|
122
|
+
} else if (code <= 0xffff) {
|
|
123
|
+
utf8.push(
|
|
124
|
+
0xe0 | (code >> 12),
|
|
125
|
+
0x80 | ((code >> 6) & 0x3f),
|
|
126
|
+
0x80 | (code & 0x3f)
|
|
127
|
+
);
|
|
128
|
+
} else {
|
|
129
|
+
utf8.push(
|
|
130
|
+
0xf0 | (code >> 18),
|
|
131
|
+
0x80 | ((code >> 12) & 0x3f),
|
|
132
|
+
0x80 | ((code >> 6) & 0x3f),
|
|
133
|
+
0x80 | (code & 0x3f)
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return new Uint8Array(utf8);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function decodeUTF8(bytes) {
|
|
141
|
+
// Manual UTF-8 decoding for QuickJS (no TextDecoder)
|
|
142
|
+
let str = "";
|
|
143
|
+
let i = 0;
|
|
144
|
+
while (i < bytes.length) {
|
|
145
|
+
let code;
|
|
146
|
+
const b = bytes[i];
|
|
147
|
+
if (b <= 0x7f) {
|
|
148
|
+
code = b;
|
|
149
|
+
i++;
|
|
150
|
+
} else if ((b & 0xe0) === 0xc0) {
|
|
151
|
+
code = ((b & 0x1f) << 6) | (bytes[i + 1] & 0x3f);
|
|
152
|
+
i += 2;
|
|
153
|
+
} else if ((b & 0xf0) === 0xe0) {
|
|
154
|
+
code =
|
|
155
|
+
((b & 0x0f) << 12) |
|
|
156
|
+
((bytes[i + 1] & 0x3f) << 6) |
|
|
157
|
+
(bytes[i + 2] & 0x3f);
|
|
158
|
+
i += 3;
|
|
159
|
+
} else {
|
|
160
|
+
code =
|
|
161
|
+
((b & 0x07) << 18) |
|
|
162
|
+
((bytes[i + 1] & 0x3f) << 12) |
|
|
163
|
+
((bytes[i + 2] & 0x3f) << 6) |
|
|
164
|
+
(bytes[i + 3] & 0x3f);
|
|
165
|
+
i += 4;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
if (code <= 0xffff) {
|
|
169
|
+
str += String.fromCharCode(code);
|
|
170
|
+
} else {
|
|
171
|
+
// Encode as surrogate pair
|
|
172
|
+
code -= 0x10000;
|
|
173
|
+
str += String.fromCharCode(0xd800 + (code >> 10), 0xdc00 + (code & 0x3ff));
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
return str;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
class File extends Blob {
|
|
180
|
+
#name;
|
|
181
|
+
#lastModified;
|
|
182
|
+
|
|
183
|
+
constructor(fileBits, fileName, options) {
|
|
184
|
+
if (arguments.length < 2) {
|
|
185
|
+
throw new TypeError(
|
|
186
|
+
"Failed to construct 'File': 2 arguments required, but only " +
|
|
187
|
+
arguments.length +
|
|
188
|
+
" present."
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
super(fileBits, options);
|
|
193
|
+
this.#name = String(fileName);
|
|
194
|
+
this.#lastModified =
|
|
195
|
+
options?.lastModified !== undefined
|
|
196
|
+
? Number(options.lastModified)
|
|
197
|
+
: Date.now();
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
get name() {
|
|
201
|
+
return this.#name;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
get lastModified() {
|
|
205
|
+
return this.#lastModified;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
toString() {
|
|
209
|
+
return "[object File]";
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
get [Symbol.toStringTag]() {
|
|
213
|
+
return "File";
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
globalThis.Blob = Blob;
|
|
218
|
+
globalThis.File = File;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// FormatJS Intl polyfills for QuickJS (no native Intl support)
|
|
2
|
+
// Order matters: getCanonicalLocales and Locale are deps of the others
|
|
3
|
+
|
|
4
|
+
import "@formatjs/intl-getcanonicallocales/polyfill-force.js";
|
|
5
|
+
import "@formatjs/intl-locale/polyfill-force.js";
|
|
6
|
+
|
|
7
|
+
import "@formatjs/intl-pluralrules/polyfill-force.js";
|
|
8
|
+
import "@formatjs/intl-pluralrules/locale-data/en";
|
|
9
|
+
|
|
10
|
+
import "@formatjs/intl-numberformat/polyfill-force.js";
|
|
11
|
+
import "@formatjs/intl-numberformat/locale-data/en";
|
|
12
|
+
|
|
13
|
+
import "@formatjs/intl-datetimeformat/polyfill-force.js";
|
|
14
|
+
import "@formatjs/intl-datetimeformat/locale-data/en";
|
|
15
|
+
import "@formatjs/intl-datetimeformat/add-all-tz.js";
|
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: quickjs
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.12.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- hmsk
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: json
|
|
@@ -47,6 +46,7 @@ extensions:
|
|
|
47
46
|
extra_rdoc_files: []
|
|
48
47
|
files:
|
|
49
48
|
- CHANGELOG.md
|
|
49
|
+
- CLAUDE.md
|
|
50
50
|
- LICENSE
|
|
51
51
|
- README.md
|
|
52
52
|
- Rakefile
|
|
@@ -78,9 +78,15 @@ files:
|
|
|
78
78
|
- ext/quickjsrb/quickjs/unicode_gen_def.h
|
|
79
79
|
- ext/quickjsrb/quickjsrb.c
|
|
80
80
|
- ext/quickjsrb/quickjsrb.h
|
|
81
|
+
- ext/quickjsrb/vendor/polyfill-file.min.js
|
|
81
82
|
- ext/quickjsrb/vendor/polyfill-intl-en.min.js
|
|
82
83
|
- lib/quickjs.rb
|
|
83
84
|
- lib/quickjs/version.rb
|
|
85
|
+
- polyfills/package-lock.json
|
|
86
|
+
- polyfills/package.json
|
|
87
|
+
- polyfills/rolldown.config.mjs
|
|
88
|
+
- polyfills/src/file.js
|
|
89
|
+
- polyfills/src/intl-en.js
|
|
84
90
|
- sig/quickjs.rbs
|
|
85
91
|
homepage: https://github.com/hmsk/quickjs.rb
|
|
86
92
|
licenses:
|
|
@@ -89,7 +95,6 @@ metadata:
|
|
|
89
95
|
homepage_uri: https://github.com/hmsk/quickjs.rb
|
|
90
96
|
source_code_uri: https://github.com/hmsk/quickjs.rb
|
|
91
97
|
changelog_uri: https://github.com/hmsk/quickjs.rb/blob/main/CHANGELOG.md
|
|
92
|
-
post_install_message:
|
|
93
98
|
rdoc_options: []
|
|
94
99
|
require_paths:
|
|
95
100
|
- lib
|
|
@@ -104,8 +109,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
104
109
|
- !ruby/object:Gem::Version
|
|
105
110
|
version: '0'
|
|
106
111
|
requirements: []
|
|
107
|
-
rubygems_version:
|
|
108
|
-
signing_key:
|
|
112
|
+
rubygems_version: 4.0.3
|
|
109
113
|
specification_version: 4
|
|
110
114
|
summary: Run binding of QuickJS
|
|
111
115
|
test_files: []
|