Skip to content
This repository has been archived by the owner on Dec 13, 2023. It is now read-only.

Commit

Permalink
feat: Populate window object
Browse files Browse the repository at this point in the history
  • Loading branch information
RomainTHD committed Oct 24, 2023
1 parent dd98663 commit 7da1e87
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 35 deletions.
45 changes: 10 additions & 35 deletions src/typechecker/envTypechecker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ import {
Stage,
type TypescriptConfig,
} from "../env";
import { NumberType, ObjectType, Type, UndefinedType } from "../types";
import { assert, type AtLeast, stringify, throwError } from "../utils";
import { Type } from "../types";
import { populateWindowObject } from "../types/populate";
import { assert, stringify, throwError } from "../utils";

interface Value extends BaseValue {
vType: Type;
Expand Down Expand Up @@ -175,39 +176,13 @@ export class EnvTypechecker extends BaseEnv<Value, ChildData> {
}

private populateEnv(): void {
const globals: { name: string; value: AtLeast<Value, "vType"> }[] = [
{
name: "undefined",
value: { vType: UndefinedType.create(), isLocal: false, isMutable: false, builtin: true },
},
{
name: "NaN",
value: { vType: NumberType.create(), isLocal: false, isMutable: false, builtin: true },
},
{
name: "Infinity",
value: { vType: NumberType.create(), isLocal: false, isMutable: false, builtin: true },
},
];

for (const { name, value } of globals) {
this.add(name, value);
}

const globalThis = ObjectType.create(
globals.map((g) => ({
name: g.name,
pType: g.value.vType,
})),
populateWindowObject().forEach((prop) =>
this.add(prop.name, {
vType: prop.vType,
isLocal: prop.isLocal ?? false,
isMutable: prop.isMutable ?? false,
builtin: true,
}),
);

this.add("globalThis", { vType: globalThis, isLocal: false, isMutable: false, builtin: true });
globalThis.add({ name: "globalThis", pType: globalThis });

this.add("window", { vType: globalThis, isLocal: false, isMutable: false, builtin: true });
globalThis.add({ name: "window", pType: globalThis });

this.add("this", { vType: globalThis, isLocal: true, isMutable: true, builtin: true });
globalThis.add({ name: "this", pType: globalThis });
}
}
28 changes: 28 additions & 0 deletions src/types/populate.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { BooleanType } from "./BooleanType";
import { FunctionType } from "./FunctionType";
import { NumberType } from "./NumberType";
import { ObjectType } from "./ObjectType";
import { populateWindowObject } from "./populate";
import { RawObjectType } from "./RawObjectType";
import { StringType } from "./StringType";

Expand Down Expand Up @@ -154,4 +155,31 @@ describe("populate", () => {
"replaceAll: (searchValue: string | RegExp, replaceValue: string) => string",
]);
});

it("should populate window", () => {
const win = populateWindowObject();
const globalThis = win.find((p) => p.name === "globalThis")?.vType;
expect(globalThis).toBeDefined();
expect(
win
.filter((p) => !["globalThis", "window", "this", "self"].includes(p.name))
.map((p) => `${p.name}: ${p.vType.toString()}`),
).toEqual([
"undefined: undefined",
"NaN: number",
"Infinity: number",
"console: unknown",
"document: object",
"alert: (message?: string) => void",
"addEventListener: (type: string, listener: (event?: unknown) => void, options?: boolean | object) => void",
"btoa: (stringToEncode: unknown) => string",
"fetch: (resource: string, options?: object) => void",
"setInterval: (func: () => void, delay?: number, args?: unknown[]) => number",
"setTimeout: (functionRef: () => void, delay?: number, args?: unknown[]) => number",
]);
expect(win.find((p) => p.name === "globalThis")?.vType).toBe(globalThis);
expect(win.find((p) => p.name === "window")?.vType).toBe(globalThis);
expect(win.find((p) => p.name === "self")?.vType).toBe(globalThis);
expect(win.find((p) => p.name === "this")?.vType).toBe(globalThis);
});
});
58 changes: 58 additions & 0 deletions src/types/populate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
type Type,
UndefinedType,
UnionType,
UnknownType,
VoidType,
} from ".";
import { IllegalStateException } from "../utils/IllegalStateException";
Expand Down Expand Up @@ -48,6 +49,9 @@ function stringToType(sTypesRaw: string): [Type, string[]] {
case "undefined":
return UndefinedType.create();

case "unknown":
return UnknownType.create();

case "void":
return VoidType.create();

Expand Down Expand Up @@ -361,3 +365,57 @@ export async function populate(): Promise<void> {
export function isPopulated(): boolean {
return populated;
}

export function populateWindowObject(): { name: string; vType: Type; isLocal?: boolean; isMutable?: boolean }[] {
const globals: { name: string; pType: Type }[] = [
createProperty("undefined", "undefined"),
createProperty("NaN", "number"),
createProperty("Infinity", "number"),
createProperty("console", "unknown"), // TODO: Create console type
createProperty("document", "object"),
createFunctionProperty("alert", [["message?", "string"]], "void"),
createFunctionProperty(
"addEventListener",
[
["type", "string"],
createFunctionParam("listener", [["event?", "unknown"]], "void"),
["options?", "boolean | object"],
],
"void",
),
createFunctionProperty("btoa", [["stringToEncode", "unknown"]], "string"),
createFunctionProperty(
"fetch",
[
["resource", "string"],
["options?", "object"],
],
"void",
),
createFunctionProperty(
"setInterval",
[createFunctionParam("func", [], "void"), ["delay?", "number"], ["args?", "unknown[]"]],
"number",
),
createFunctionProperty(
"setTimeout",
[createFunctionParam("functionRef", [], "void"), ["delay?", "number"], ["args?", "unknown[]"]],
"number",
),
];

const globalThis = ObjectType.create(globals);

globalThis.add({ name: "globalThis", pType: globalThis });
globalThis.add({ name: "window", pType: globalThis });
globalThis.add({ name: "this", pType: globalThis });
globalThis.add({ name: "self", pType: globalThis });

return [
...globals.map((g) => ({ name: g.name, vType: g.pType })),
{ name: "globalThis", vType: globalThis },
{ name: "window", vType: globalThis },
{ name: "this", vType: globalThis, isLocal: true, isMutable: true },
{ name: "self", vType: globalThis },
];
}

0 comments on commit 7da1e87

Please sign in to comment.