Source code
Revision control
Copy as Markdown
Other Tools
/* Any copyright is dedicated to the Public Domain.
import assert from "assert";
import globalsUtils from "../lib/globals.mjs";
import path from "path";
var { getGlobalsForCode } = globalsUtils;
/* global describe, it, beforeEach */
describe("global variables", function () {
it("should reflect top-level this property assignment", function () {
const globals = getGlobalsForCode(`
this.foo = 10;
`);
assert.deepEqual(globals, [{ name: "foo", writable: true }]);
});
it("should reflect this property assignment inside block", function () {
const globals = getGlobalsForCode(`
{
this.foo = 10;
}
`);
assert.deepEqual(globals, [{ name: "foo", writable: true }]);
});
it("should ignore this property assignment inside function declaration", function () {
const globals = getGlobalsForCode(`
function f() {
this.foo = 10;
}
`);
assert.deepEqual(globals, [{ name: "f", writable: true }]);
});
it("should ignore this property assignment inside function expression", function () {
const globals = getGlobalsForCode(`
(function f() {
this.foo = 10;
});
`);
assert.deepEqual(globals, []);
});
it("should ignore this property assignment inside method", function () {
const globals = getGlobalsForCode(`
({
method() {
this.foo = 10;
}
});
`);
assert.deepEqual(globals, []);
});
it("should ignore this property assignment inside accessor", function () {
const globals = getGlobalsForCode(`
({
get x() {
this.foo = 10;
},
set x(v) {
this.bar = 10;
}
});
`);
assert.deepEqual(globals, []);
});
it("should reflect this property assignment inside arrow function", function () {
const globals = getGlobalsForCode(`
() => {
this.foo = 10;
};
`);
assert.deepEqual(globals, [{ name: "foo", writable: true }]);
});
it("should ignore this property assignment inside arrow function inside function expression", function () {
const globals = getGlobalsForCode(`
(function f() {
() => {
this.foo = 10;
};
});
`);
assert.deepEqual(globals, []);
});
it("should ignore this property assignment inside class static", function () {
const globals = getGlobalsForCode(`
class A {
static {
this.foo = 10;
(() => {
this.bar = 10;
})();
}
}
`);
assert.deepEqual(globals, [{ name: "A", writable: true }]);
});
it("should ignore this property assignment inside class property", function () {
const globals = getGlobalsForCode(`
class A {
a = this.foo = 10;
b = (() => {
this.bar = 10;
})();
}
`);
assert.deepEqual(globals, [{ name: "A", writable: true }]);
});
it("should ignore this property assignment inside class static property", function () {
const globals = getGlobalsForCode(`
class A {
static a = this.foo = 10;
static b = (() => {
this.bar = 10;
})();
}
`);
assert.deepEqual(globals, [{ name: "A", writable: true }]);
});
it("should ignore this property assignment inside class private property", function () {
const globals = getGlobalsForCode(`
class A {
#a = this.foo = 10;
#b = (() => {
this.bar = 10;
})();
}
`);
assert.deepEqual(globals, [{ name: "A", writable: true }]);
});
it("should ignore this property assignment inside class static private property", function () {
const globals = getGlobalsForCode(`
class A {
static #a = this.foo = 10;
static #b = (() => {
this.bar = 10;
})();
}
`);
assert.deepEqual(globals, [{ name: "A", writable: true }]);
});
it("should reflect lazy getters", function () {
const globals = getGlobalsForCode(`
ChromeUtils.defineESModuleGetters(this, {
A: "B",
});
`);
assert.deepEqual(globals, [{ name: "A", writable: true, explicit: true }]);
});
});
function getFullTestFilePath(filename) {
return import.meta.dirname + "/globals-data/" + filename;
}
describe("global import - file trees", () => {
function callFn(filename) {
return globalsUtils.ensureFileTree({
filePath: getFullTestFilePath(filename),
});
}
function stripPathsSet(set) {
return new Set(set.values().map(v => path.basename(v)));
}
function stripPathsMap(map) {
return new Map(
map.entries().map(([k, v]) => [path.basename(k), stripPathsSet(v)])
);
}
beforeEach(() => {
globalsUtils.clearFileImportGraph();
});
it("should report errors where import-globals-from tries to import mjs files", () => {
assert.throws(
() => {
callFn("import-globals-from-invalid.js");
},
{
message:
"import-globals-from does not support module files - use a direct import instead",
}
);
});
function assertImportGraph(testFilename, expectedMap, expectedSet) {
let fileImportGraph = callFn(testFilename);
assert.deepEqual(stripPathsMap(fileImportGraph), expectedMap);
assert.deepEqual(
stripPathsSet(
fileImportGraph.getSubGraph(getFullTestFilePath(testFilename))
),
expectedSet
);
}
it("should build a tree when importing globals from another file", () => {
assertImportGraph(
"import-globals-from-1.js",
new Map([
["import-globals-from-1-additional.js", new Set()],
[
"import-globals-from-1.js",
new Set(["import-globals-from-1-additional.js"]),
],
]),
new Set([
"import-globals-from-1-additional.js",
"import-globals-from-1.js",
])
);
});
it("should handle loadSubScript", () => {
assertImportGraph(
"loadSubScript-1.js",
new Map([
["loadSubScript-1.js", new Set(["loadSubScript-1-additional.js"])],
["loadSubScript-1-additional.js", new Set([])],
]),
new Set(["loadSubScript-1-additional.js", "loadSubScript-1.js"])
);
});
it("should handle importScripts in a worker", () => {
assertImportGraph(
"importScripts-1.js",
new Map([
["importScripts-1.js", new Set(["importScripts-1-additional.js"])],
["importScripts-1-additional.js", new Set([])],
]),
new Set(["importScripts-1-additional.js", "importScripts-1.js"])
);
});
it("should build a tree handling a simple circular import", () => {
assertImportGraph(
"import-globals-from-circular-1.js",
new Map([
[
"import-globals-from-circular-1.js",
new Set(["import-globals-from-circular-2.js"]),
],
[
"import-globals-from-circular-2.js",
new Set(["import-globals-from-circular-1.js"]),
],
]),
new Set([
"import-globals-from-circular-2.js",
"import-globals-from-circular-1.js",
])
);
});
it("should build a tree handling complex circular import", () => {
assertImportGraph(
"import-globals-from-circular-3.js",
new Map([
[
"import-globals-from-circular-3.js",
new Set(["import-globals-from-circular-4.js"]),
],
[
"import-globals-from-circular-4.js",
new Set(["import-globals-from-circular-5.js"]),
],
[
"import-globals-from-circular-5.js",
new Set(["import-globals-from-circular-3.js"]),
],
]),
new Set([
"import-globals-from-circular-3.js",
"import-globals-from-circular-4.js",
"import-globals-from-circular-5.js",
])
);
});
});
describe("global import - correct globals", () => {
beforeEach(() => {
globalsUtils.clearFileImportGraph();
});
function callFn(filename) {
return globalsUtils.getGlobalsForFile({
filePath: getFullTestFilePath(filename),
});
}
it("should return the globals for the simple import case", () => {
let globals = callFn("import-globals-from-1.js");
assert.deepEqual(globals, [
{ name: "foo1", writable: true },
{ explicit: true, name: "foo", writable: true },
{ name: "bar1", writable: true },
{ explicit: true, name: "bar", writable: true },
]);
});
it("should return the globals for a simple circular import case", () => {
let globals = callFn("import-globals-from-circular-1.js");
assert.deepEqual(
globals,
[
{ name: "circ1", writable: true },
{ name: "circ2", writable: true },
],
"should return the correct global when getting the globals for the first file"
);
globals = callFn("import-globals-from-circular-2.js");
assert.deepEqual(
globals,
[
{ name: "circ2", writable: true },
{ name: "circ1", writable: true },
],
"should return the correct global when getting the globals for the second file"
);
});
it("should return the globals for a simple circular import case", () => {
let globals = callFn("import-globals-from-circular-3.js");
assert.deepEqual(
globals,
[
{ name: "circ3", writable: true },
{ name: "circ4", writable: true },
{ name: "circ5", writable: true },
],
"should return the correct global when getting the globals for the first file"
);
globals = callFn("import-globals-from-circular-4.js");
assert.deepEqual(
globals,
[
{ name: "circ4", writable: true },
{ name: "circ5", writable: true },
{ name: "circ3", writable: true },
],
"should return the correct global when getting the globals for the second file"
);
globals = callFn("import-globals-from-circular-5.js");
assert.deepEqual(
globals,
[
{ name: "circ5", writable: true },
{ name: "circ3", writable: true },
{ name: "circ4", writable: true },
],
"should return the correct global when getting the globals for the third file"
);
});
});