Recap: (incomplete draft) semantics of import and export versus require


A fine-grained breakdown of the semantics of import and export took unexpected directions in our discussion yesterday. The static semantics alone can be sometimes surprising to predict with the added the complexities of somehow dynamically modifying namespaces.

I will try to walk through what we touched upon during yesterday’s meeting in this thread gradually until next Tuesday.

Execution Order

Upon reflection, one concern that we were indirectly getting at yesterday was largely related to the execution order semantics of modules being attenuated by narrowing or by remapping.

We can show the effect of execution order very easily once eliminate the complexity of cyclic references as follows:

// ./counter.js
export let counter = 0;
export const increment = number => counter += number;
// ./a.js
import {increment} from './counter.js';
export const step = 1;
export const a1 = increment(step);
export const a2 = increment(step);
export const a3 = increment(step);
export const a4 = increment(step);
export const a5 = increment(step);
// ./b.js
import {increment} from './counter.js';
export const step = 0.1;
export const b1 = increment(step);
export const b2 = increment(step);
export const b3 = increment(step);
export const b4 = increment(step);
export const b5 = increment(step);
// ./a-b.js
import * as a from './a.js';
import * as b from './b.js';

console.log({a, b});
// { 
//   a: { a1: 1, a2: 2, a3: 3, a4: 4, a5: 5, step: 1 },
//   b: { b1: 5.1, b2: 5.2, b3: 5.3, b4: 5.4, b5: 5.5, step: 0.1 } 
// }
// ./b-a.js
import * as b from './b.js';
import * as a from './a.js';

console.log({b, a});
// {
//   b: { b1: 0.1, b2: 0.2, b3: 0.3, b4: 0.4, b5: 0.5, step: 0.1 },
//   a: { a1: 1.5, a2: 2.5, a3: 3.5, a4: 4.5, a5: 5.5, step: 1 },
// }

I am not sure how to get to the important points where attenuated modules and the original modules they reflect could potentially cause problems when first instantiated in the same graph. I don’t think circularity alone is the concern here, because it takes a lot of hard effort to make a scenario for that, but if execution order of non-attenuated modules is influenced by compartmentalized imports, they may indirectly influence at least through side-effects the behaviour in other compartments or even in a parent one.

More to follow…