Skip to content

Commit d3ac2a7

Browse files
committed
feat: polyfills setup
1 parent 3421fed commit d3ac2a7

23 files changed

+476
-283
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
"fs-gjs": "^1.0.1",
4747
"rimraf": "^4.4.1",
4848
"tar": "^6.2.0",
49-
"termx-markup": "1.1.1",
49+
"termx-markup": "~2.0.2",
5050
"whatwg-url-without-unicode": "^8.0.0-3"
5151
},
5252
"devDependencies": {

scripts/build.cjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ async function main() {
3232
}),
3333
// Build polyfill packages
3434
await build({
35-
target: "es2022",
35+
target: "ESNext",
3636
srcDir: p("src/polyfills"),
3737
outDir: p("polyfills"),
3838
tsConfig: p("tsconfig.json"),

src/esbuild-plugins/import-polyfills/create-node-polyfill-map.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type esbuild from "esbuild";
22
import path from "path";
33
import type { Config } from "../../config/config-type";
4+
import { getDirPath } from "../../get-dirpath/get-dirpath";
45
import type { DeepReadonly, Program } from "../../programs/base";
56

67
type PolyfillMapDef = {
@@ -10,19 +11,18 @@ type PolyfillMapDef = {
1011
};
1112

1213
export const createNodePolyfillMap = (polyfills: Array<PolyfillMapDef>) => {
14+
const rootPath = getDirPath();
1315
return {
1416
addResolvers(program: Program, build: esbuild.PluginBuild) {
1517
for (const pollyfill of polyfills) {
1618
if (pollyfill.configFlag(program.config)) {
1719
build.onResolve({ filter: pollyfill.matcher }, (args) => {
1820
return build.resolve(
19-
"react-gnome/" + path.join("polyfills/esm", pollyfill.filename),
21+
path.join(rootPath, "polyfills/esm", pollyfill.filename),
2022
{
21-
importer: args.importer,
22-
namespace: args.namespace,
23+
resolveDir: rootPath,
2324
kind: args.kind,
24-
pluginData: args.pluginData,
25-
resolveDir: args.resolveDir,
25+
importer: args.importer,
2626
},
2727
);
2828
});
Lines changed: 7 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,33 @@
11
import type esbuild from "esbuild";
2+
import path from "path";
23
import type { Program } from "../../programs/base";
34
import { createNodePolyfillMap } from "./create-node-polyfill-map";
45

56
export const POLYFILL_IMPORT_NS = "react-gnome-polyfills";
67

78
const NodePolyfills = createNodePolyfillMap([
89
{
9-
matcher: /^(fs)|(node:fs)$/,
10+
matcher: /^(fs|node:fs)$/,
1011
configFlag: (c) => !!c.polyfills?.node?.fs,
1112
filename: "fs.mjs",
1213
},
1314
{
14-
matcher: /^(fs\/promises)|(node:fs\/promises)$/,
15+
matcher: /^(fs\/promises|node:fs\/promises)$/,
1516
configFlag: (c) => !!c.polyfills?.node?.fs,
1617
filename: "fs-promises.mjs",
1718
},
1819
{
19-
matcher: /^(path)|(node:path)$/,
20+
matcher: /^(path|node:path)$/,
2021
configFlag: (c) => !!c.polyfills?.node?.path,
2122
filename: "path.mjs",
2223
},
2324
{
24-
matcher: /^(querystring)|(node:querystring)$/,
25+
matcher: /^(querystring|node:querystring)$/,
2526
configFlag: (c) => !!c.polyfills?.node?.querystring,
2627
filename: "querystring.mjs",
2728
},
2829
{
29-
matcher: /^(os)|(node:os)$/,
30+
matcher: /^(os|node:os)$/,
3031
configFlag: (c) => !!c.polyfills?.node?.os,
3132
filename: "node-os.mjs",
3233
},
@@ -44,34 +45,13 @@ export const importPolyfillsPlugin = (program: Program) => {
4445
build.onResolve({ filter: /.*/ }, (arg) => {
4546
if (customPoly.importName === arg.path) {
4647
return {
47-
path: customPoly.filepath,
48-
namespace: POLYFILL_IMPORT_NS,
48+
path: path.join(program.cwd, customPoly.filepath),
4949
};
5050
}
5151
});
5252
}
5353
}
5454
}
55-
56-
if (program.config.customPolyfills) {
57-
build.onLoad(
58-
{
59-
filter: /.*/,
60-
namespace: POLYFILL_IMPORT_NS,
61-
},
62-
(args) => {
63-
return {
64-
contents: /* js */ `
65-
import * as _mod from "${args.path}";
66-
const _default = _mod.default ?? _mod;
67-
export default _default;
68-
export * from "${args.path}";
69-
`.trim(),
70-
resolveDir: program.cwd,
71-
};
72-
},
73-
);
74-
}
7555
},
7656
};
7757
};

src/esbuild-plugins/react-gnome/default-gi-imports.ts

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { html, Output } from "termx-markup";
12
import type { Config } from "../../config/config-type";
23

34
class GiImport {
@@ -26,12 +27,38 @@ export class GiImports {
2627
versions.Soup ??= "2.4";
2728
}
2829

30+
private printVersionConflict(name: string, v1: string, v2: string) {
31+
Output.print(html`
32+
<span>
33+
<span color="yellow">WARN:</span>
34+
<span>
35+
GI dependency (${name}) version conflict. ${v1} and ${v2} are both
36+
required at the same time.
37+
</span>
38+
</span>
39+
`);
40+
}
41+
2942
add(name: string, version?: string) {
30-
if (this.imports.has(name)) return;
43+
if (this.imports.has(name)) {
44+
const im = this.imports.get(name)!;
45+
if (version != null) {
46+
if (im.version == null) {
47+
im.setVersion(version);
48+
} else if (version !== im.version) {
49+
this.printVersionConflict(name, im.version, version!);
50+
}
51+
}
52+
return;
53+
}
3154

3255
if (name in this.versions) {
3356
// @ts-expect-error
34-
version = this.versions[name];
57+
const versionOverride = this.versions[name];
58+
if (version != null && version !== versionOverride) {
59+
this.printVersionConflict(name, versionOverride, version!);
60+
}
61+
version = versionOverride;
3562
}
3663

3764
const giImport = new GiImport(name);

src/esbuild-plugins/react-gnome/react-gnome-plugin.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,14 @@ class ExternalImport {
2222
}
2323
}
2424

25-
export const reactGnomePlugin = (program: Program) => {
25+
export type GnomePluginOptions = {
26+
giRequirements?: [string, string | undefined][];
27+
};
28+
29+
export const reactGnomePlugin = (
30+
program: Program,
31+
options: GnomePluginOptions,
32+
) => {
2633
const externalPackages = new Set(program.config.externalPackages ?? []);
2734
externalPackages.add("system");
2835
externalPackages.add("gettext");
@@ -33,6 +40,10 @@ export const reactGnomePlugin = (program: Program) => {
3340
const gi = new GiImports(program.config.giVersions);
3441
const externalImports: ExternalImport[] = [];
3542

43+
for (const [name, version] of options.giRequirements ?? []) {
44+
gi.add(name, version);
45+
}
46+
3647
if (program.resources) {
3748
build.onLoad(
3849
{

src/polyfills/abort-controller.ts

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1-
namespace AbortControllerPolyfill {
1+
import { registerPolyfills } from "./shared/polyfill-global";
2+
3+
registerPolyfills(
4+
"AbortController",
5+
"AbortSignal",
6+
"AbortError",
7+
)(() => {
28
enum Events {
39
Abort = "abort",
410
}
@@ -48,14 +54,14 @@ namespace AbortControllerPolyfill {
4854
}
4955
}
5056

51-
export class AbortError extends Error {
57+
class AbortError extends Error {
5258
constructor(message: string) {
5359
super(message);
5460
this.name = "AbortError";
5561
}
5662
}
5763

58-
export class AbortSignal {
64+
class AbortSignal {
5965
static abort(reason?: any) {
6066
const signal = new AbortSignal();
6167
signal._abort(reason ?? new AbortError("Signal was aborted."));
@@ -118,7 +124,7 @@ namespace AbortControllerPolyfill {
118124
}
119125
}
120126

121-
export class AbortController {
127+
class AbortController {
122128
private readonly _signal = new AbortSignal();
123129

124130
get signal(): AbortSignal {
@@ -129,8 +135,10 @@ namespace AbortControllerPolyfill {
129135
this._signal["_abort"]();
130136
}
131137
}
132-
}
133138

134-
export const AbortController = AbortControllerPolyfill.AbortController;
135-
export const AbortSignal = AbortControllerPolyfill.AbortSignal;
136-
export const AbortError = AbortControllerPolyfill.AbortError;
139+
return {
140+
AbortController,
141+
AbortSignal,
142+
AbortError,
143+
};
144+
});

src/polyfills/base64.ts

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,22 @@
11
import GLib from "gi://GLib?version=2.0";
2+
import { registerPolyfills } from "./shared/polyfill-global";
23

3-
export function atob(data: string) {
4-
const decodedData = GLib.base64_decode(data);
5-
return new TextDecoder().decode(decodedData);
6-
}
4+
registerPolyfills(
5+
"atob",
6+
"btoa",
7+
)(() => {
8+
function atob(data: string) {
9+
const decodedData = GLib.base64_decode(data);
10+
return new TextDecoder().decode(decodedData);
11+
}
712

8-
export function btoa(data: string) {
9-
const encodedData = new TextEncoder().encode(data);
10-
return GLib.base64_encode(encodedData)!;
11-
}
13+
function btoa(data: string) {
14+
const encodedData = new TextEncoder().encode(data);
15+
return GLib.base64_encode(encodedData)!;
16+
}
17+
18+
return {
19+
atob,
20+
btoa,
21+
};
22+
});

src/polyfills/blob.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
11
import { Blob as BlobPolyfill } from "buffer";
2+
import { registerPolyfills } from "./shared/polyfill-global";
23

3-
export const Blob = BlobPolyfill;
4+
registerPolyfills("Blob")(() => {
5+
return {
6+
Blob: BlobPolyfill,
7+
};
8+
});

src/polyfills/buffer.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
11
import { Buffer as BufferPolyfill } from "buffer";
2+
import { registerPolyfills } from "./shared/polyfill-global";
23

3-
export const Buffer = BufferPolyfill;
4+
registerPolyfills("Buffer")(() => {
5+
return {
6+
Buffer: BufferPolyfill,
7+
};
8+
});

0 commit comments

Comments
 (0)