Skip to content

Commit ba2f24e

Browse files
jashkenasmbostock
authored andcommitted
Tests for circular imports and circular import withs
1 parent 6add2bc commit ba2f24e

File tree

2 files changed

+125
-1
lines changed

2 files changed

+125
-1
lines changed

src/module.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ function module_derive(injects, injectModule) {
7373
const module = variable._inputs[0]._module;
7474
const source = module._source || module;
7575
if (source === this) { // circular import-with!
76-
console.warn("circular module definition; ignoring");
76+
console.warn("circular module definition; ignoring"); // eslint-disable-line no-console
7777
return;
7878
}
7979
modules.add(source);

test/variable/import-test.js

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,127 @@ tape("variable.import(name, module) can import a variable that depends on a muta
4242
const baz = main.variable(true).define("baz", ["bar"], bar => `baz-${bar}`);
4343
test.deepEqual(await valueof(baz), {value: "baz-13"});
4444
});
45+
46+
tape("variable.import() allows non-circular imported values from circular imports", async test => {
47+
const runtime = new Runtime();
48+
const a = runtime.module();
49+
const b = runtime.module();
50+
a.define("foo", [], () => "foo");
51+
b.define("bar", [], () => "bar");
52+
a.import("bar", b);
53+
b.import("foo", a);
54+
const afoobar = a.variable(true).define("foobar", ["foo", "bar"], (foo, bar) => 'a' + foo + bar);
55+
const bfoobar = b.variable(true).define("foobar", ["foo", "bar"], (foo, bar) => 'b' + foo + bar);
56+
test.deepEqual(await valueof(afoobar), {value: "afoobar"});
57+
test.deepEqual(await valueof(bfoobar), {value: "bfoobar"});
58+
});
59+
60+
tape("variable.import() fails when importing creates a circular reference", async test => {
61+
const runtime = new Runtime();
62+
const a = runtime.module();
63+
const b = runtime.module();
64+
a.import("bar", b);
65+
a.define("foo", ["bar"], (bar) => `foo${bar}`);
66+
b.import("foo", a);
67+
b.define("bar", ["foo"], (foo) => `${foo}bar`);
68+
const afoobar = a.variable(true).define("foobar", ["foo", "bar"], (foo, bar) => 'a' + foo + bar);
69+
const bbarfoo = b.variable(true).define("barfoo", ["bar", "foo"], (bar, foo) => 'b' + bar + foo);
70+
test.deepEqual(await valueof(afoobar), {error: "RuntimeError: foo could not be resolved"});
71+
test.deepEqual(await valueof(bbarfoo), {error: "RuntimeError: bar could not be resolved"});
72+
});
73+
74+
tape(
75+
"variable.import() fails to resolve variables derived from a direct circular import with",
76+
async test => {
77+
const runtime = new Runtime();
78+
let a1, b1, a2, b2;
79+
80+
function define1() {
81+
const main = runtime.module();
82+
a1 = main.variable(true).define("a", function() {
83+
return 1;
84+
});
85+
b1 = main.variable(true).define(["b"], function(b) {
86+
return b;
87+
});
88+
const child1 = runtime.module(define2).derive(["a"], main);
89+
main.import("b", child1);
90+
return main;
91+
}
92+
93+
function define2() {
94+
const main = runtime.module();
95+
b2 = main.variable(true).define("b", function() {
96+
return 2;
97+
});
98+
a2 = main.variable(true).define(["a"], function(a) {
99+
return a;
100+
});
101+
const child1 = runtime.module(define1).derive(["b"], main);
102+
main.import("a", child1);
103+
return main;
104+
}
105+
define1();
106+
107+
test.deepEqual(await valueof(a1), {value: 1});
108+
test.deepEqual(await valueof(b1), {error: 'RuntimeError: b could not be resolved'});
109+
test.deepEqual(await valueof(a2), {error: 'RuntimeError: a could not be resolved'});
110+
test.deepEqual(await valueof(b2), {value: 2});
111+
}
112+
);
113+
114+
tape(
115+
"variable.import() also fails to resolve variables derived from an indirectly circular import with",
116+
async test => {
117+
const runtime = new Runtime();
118+
let a, b, c, importA, importB, importC;
119+
120+
function define1() {
121+
const main = runtime.module();
122+
a = main.variable(true).define("a", function() {
123+
return 1;
124+
});
125+
importC = main.variable(true).define(["c"], function(c) {
126+
return c;
127+
});
128+
const child3 = runtime.module(define3).derive(["a"], main);
129+
main.import("c", child3);
130+
return main;
131+
}
132+
133+
function define2() {
134+
const main = runtime.module();
135+
b = main.variable(true).define("b", function() {
136+
return 2;
137+
});
138+
importA = main.variable(true).define(["a"], function(a) {
139+
return a;
140+
});
141+
const child1 = runtime.module(define1).derive(["b"], main);
142+
main.import("a", child1);
143+
return main;
144+
}
145+
146+
function define3() {
147+
const main = runtime.module();
148+
c = main.variable(true).define("c", function() {
149+
return 3;
150+
});
151+
importB = main.variable(true).define(["b"], function(b) {
152+
return b;
153+
});
154+
const child2 = runtime.module(define2).derive(["c"], main);
155+
main.import("b", child2);
156+
return main;
157+
}
158+
159+
define1();
160+
161+
test.deepEqual(await valueof(a), {value: 1});
162+
test.deepEqual(await valueof(b), {value: 2});
163+
test.deepEqual(await valueof(c), {value: 3});
164+
test.deepEqual(await valueof(importA), {error: 'RuntimeError: a could not be resolved'});
165+
test.deepEqual(await valueof(importB), {error: 'RuntimeError: b could not be resolved'});
166+
test.deepEqual(await valueof(importC), {error: 'RuntimeError: c could not be resolved'});
167+
}
168+
);

0 commit comments

Comments
 (0)