I have an HTML5 app which I want to embed multiple times on a single page. It works partially using the following syntax:
var myworld128 = lime.embed ("Main", "content128" …
var myworld129 = lime.embed ("Main", "content129" …
It creates the stage in both div#content128 and div#content129.
However, it seems that myworld128 and myworld129 have access to each other’s data. In particular, the app is using PureMVC (single core) which is a singleton facade, and when the one Main gets embedded and creates its ApplicationMediator, the other detects that it already exists.
How can I completely isolate these instances?
Bink
September 22, 2025, 10:32am
2
It’s just a thought and I haven’t tried this, but might two <iframe> 's be useful here?
This is part of a CMS integration so I’m trying to avoid that if possible.
Pretty much anything that’s static in Haxe (which usually includes singletons) is going to be shared by default. However, it may be possible to initialize the Haxe classes in JS twice. To this, you’d need to modify Lime’s output.js template in some way:
var $lime_init = (function ($hx_exports, $global) { "use strict"; var $hx_script = (function (exports, global) { ::SOURCE_FILE::
});::if false::
/*
Don't insert or remove any line breaks in the code above this line!
::SOURCE_FILE:: must start on the first line.
Breakpoints in debug builds won't work if this file's line numbers don't
match the .js.map file's expected line numbers exactly.
Additionally, the }); after ::SOURCE_FILE:: must appear on the next line
to avoid it getting ignored in a // comment at the end of ::SOURCE_FILE::.
*/
::end::
if (typeof self !== "undefined" && self.constructor.name.includes("Worker")) {
// No need for exports in a worker context, just initialize statics.
$hx_script({}, $global);
} else {
$hx_exports.lime = $hx_exports.lime || {};
$hx_exports.lime.$scripts = $hx_exports.lime.$scripts || {};
This file has been truncated. show original
The ::SOURCE_FILE:: token is where the Haxe-generated JS code goes. Notice that it’s inside a $lime_init function. This function, or maybe the $hx_script function that’s created inside $lime_init, could potentially be called more than once with different arguments. This should allow the initialization of separate instances of the Haxe classes, meaning that they wouldn’t be shared.
You likely wouldn’t be able to call lime.embed the same way that you are now because you’d actually need two separate versions of lime.embed. Or maybe you could replace lime.embed with a function that calls $lime_init each time, so that it initializes separate instances.
Just some ideas. I haven’t tried this myself, but it seems like it should be possible.
Thanks for this, I am investigating and will report back!
Well Claude Sonnet 4 solved this in just a few moments…
var $lime_init = (function ($hx_exports, $global) { "use strict"; var $hx_script = (function (exports, global) { ::SOURCE_FILE::
});::if false::
/*
Don't insert or remove any line breaks in the code above this line!
::SOURCE_FILE:: must start on the first line.
Breakpoints in debug builds won't work if this file's line numbers don't
match the .js.map file's expected line numbers exactly.
Additionally, the }); after ::SOURCE_FILE:: must appear on the next line
to avoid it getting ignored in a // comment at the end of ::SOURCE_FILE::.
*/
::end::
if (typeof self !== "undefined" && self.constructor.name.includes("Worker")) {
// No need for exports in a worker context, just initialize statics.
$hx_script({}, $global);
} else {
$hx_exports.lime = $hx_exports.lime || {};
$hx_exports.lime.$scripts = $hx_exports.lime.$scripts || {};
$hx_exports.lime.$scripts["::APP_FILE::"] = $hx_script;
// Store original embed function if it exists
var originalEmbed = $hx_exports.lime.embed;
$hx_exports.lime.embed = function (projectName) {
// Create isolated context for each embed call
var isolatedGlobal = {};
var isolatedExports = {};
// Copy necessary global properties to isolated context
for (var key in $global) {
if (key !== 'lime' && typeof $global[key] !== 'function') {
try {
isolatedGlobal[key] = $global[key];
} catch (e) {
// Skip properties that can't be copied
}
}
}
// Add essential global functions/objects that apps might need
isolatedGlobal.console = $global.console;
isolatedGlobal.setTimeout = $global.setTimeout;
isolatedGlobal.setInterval = $global.setInterval;
isolatedGlobal.clearTimeout = $global.clearTimeout;
isolatedGlobal.clearInterval = $global.clearInterval;
isolatedGlobal.requestAnimationFrame = $global.requestAnimationFrame;
isolatedGlobal.cancelAnimationFrame = $global.cancelAnimationFrame;
isolatedGlobal.document = $global.document;
isolatedGlobal.window = $global.window;
var script = $hx_exports.lime.$scripts[projectName];
if (!script) throw Error("Cannot find project name \"" + projectName + "\"");
// Execute script in isolated context
script(isolatedExports, isolatedGlobal);
// Don't pollute the main exports object
// Instead return the isolated exports
var lime = isolatedExports.lime;
if (lime && lime.embed && lime.embed !== $hx_exports.lime.embed) {
lime.embed.apply(lime, arguments);
}
return isolatedExports;
};
}
::if embeddedLibraries::::foreach embeddedLibraries::
::__current__::::end::::end::
if (typeof define === "function" && define.amd) {
define([], function () { return $hx_exports.lime; });
define.__amd = define.amd;
define.amd = null;
}
})
$lime_init(typeof exports !== "undefined" ? exports : typeof define === "function" && define.amd ? {} : typeof window !== "undefined" ? window : typeof self !== "undefined" ? self : this,
typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : this);
::if embeddedLibraries::::foreach embeddedLibraries::
::__current__::::end::::end::
if (typeof define === "function" && define.__amd) {
define.amd = define.__amd;
delete define.__amd;
}
Could not have done it without your help though @joshtynjala so thanks again!
If anyone comes here later and is confused by this solution, remember:
First create a templates/html5 directory in your project and copy the output.js there. My code above is modified from Josh’s link.
The project.xml needs:
<template path="templates" />
Should be good to compile after that.
2 Likes