Módulos Appcelerator y CommonJS (caché y referencias circulares)

Aquí está la cosa:

Estoy utilizando la forma CommonJS de hacer que mi aplicación móvil (iPhone / Android) sea modular. No hay sorpresa allí. Pero hay una cosa que no puedo entender.

CommonJS me permite crear variables privadas ESTÁTICAS, lo que me permite crear singletons a gusto. Esto, creo que al menos, se debe a que el contenido de un archivo que se obtienerequire()d se lee solo una vez y luego el objeto de exportación (que se inicializa solo una vez) se devuelve cada vez.

Pero cuando creo una referencia circular como se ve a continuación, el código dentro del módulo incluido se ejecuta cada vez.

Espere... Lo curioso es que, mientras escribo esta pregunta, de repente me doy cuenta de que ninguna de las llamadas arequire() finalice antes de que comience el siguiente (de ahí el desbordamiento de pila que se muestra a continuación).

¿Alguna idea sobre si estoy en el camino o no? Son más de las cinco de la madrugada aquí, así que todas las apuestas están apagadas en lo que a mí respecta: D.

EJEMPLOS:

Ver esta pieza de código, define un singleton:

/* Singleton.js */

exports.getSingleton = getSingleton;

function getSingleton(name) {
  if (!instance) {
    instance = new Thing(name);
  }

  return instance;
}

function Thing(name) {
  this.name = name;
}

var instance;

I require() este archivo como tal:

var theFirstThing = require('Singleton').getSingleton('first');
Ti.API.info('first: ' + theFirstThing.name)

var possiblyAnotherOtherThing = require('Singleton').getSingleton('second');
Ti.API.info('second: ' + possiblyAnotherOtherThing.name);

La salida es:

[DEBUG] loading: /path/to/sim/MyApp.app/app.js, resource: app_js
[DEBUG] loading: /path/to/sim/MyApp.app/Singleton.js, resource: Singleton_js
[INFO] first: first
[INFO] second: first

¿Por qué entonces las referencias circulares como las siguientes no funcionan? (Es posible que ya haya respondido esto, coméntelo / respondo si lo desea).

app.js

require('Banana');

Pinapple.js

require('Banana');

Banana.js

require('Pineapple');

Porque la salida es esta:

[DEBUG] loading: /path/to/simulator/MyApp.app/app.js, resource: app_js
[DEBUG] loading: /path/to/simulator/MyApp.app/Banana.js, resource: Banana_js
[DEBUG] loading: /path/to/simulator/MyApp.app/Pineapple.js, resource: Pineapple_js
[DEBUG] loading: /path/to/simulator/MyApp.app/Banana.js, resource: Banana_js
[DEBUG] loading: /path/to/simulator/MyApp.app/Pineapple.js, resource: Pineapple_js
[DEBUG] loading: /path/to/simulator/MyApp.app/Banana.js, resource: Banana_js
[DEBUG] loading: /path/to/simulator/MyApp.app/Pineapple.js, resource: Pineapple_js
[DEBUG] loading: /path/to/simulator/MyApp.app/Banana.js, resource: Banana_js

/* etcetera (total of 15 times back and forth) */

[DEBUG] loading: /path/to/simulator/MyApp.app/Pineapple.js, resource: Pineapple_js
[DEBUG] loading: /path/to/simulator/MyApp.app/Banana.js, resource: Banana_js
[DEBUG] loading: /path/to/simulator/MyApp.app/Pineapple.js, resource: Pineapple_js
[ERROR] Script Error = Maximum call stack size exceeded. (unknown file)

Respuestas a la pregunta(1)

Su respuesta a la pregunta