Index: ps/trunk/binaries/data/mods/public/simulation/components/Attack.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/Attack.js +++ ps/trunk/binaries/data/mods/public/simulation/components/Attack.js @@ -440,9 +440,8 @@ let template = this.template[type]; if (!template) template = this.template[type.split(".")[0]].Splash; - if (template.Bonuses) - return clone(template.Bonuses); - return null; + + return template.Bonuses || null; }; /** Index: ps/trunk/binaries/data/mods/public/simulation/components/DeathDamage.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/DeathDamage.js +++ ps/trunk/binaries/data/mods/public/simulation/components/DeathDamage.js @@ -57,9 +57,7 @@ DeathDamage.prototype.GetBonusTemplate = function() { - if (this.template.Bonuses) - return clone(this.template.Bonuses); - return null; + return this.template.Bonuses || null; }; DeathDamage.prototype.CauseDeathDamage = function() Index: ps/trunk/binaries/data/mods/public/simulation/components/tests/setup.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/tests/setup.js +++ ps/trunk/binaries/data/mods/public/simulation/components/tests/setup.js @@ -8,23 +8,23 @@ Engine.RegisterComponentType = function(iid, name, ctor) { TS_ASSERT(!g_ComponentTypes[name]); - g_ComponentTypes[name] = { iid: iid, ctor: ctor }; + g_ComponentTypes[name] = { "iid": iid, "ctor": ctor }; }; Engine.RegisterSystemComponentType = function(iid, name, ctor) { TS_ASSERT(!g_ComponentTypes[name]); - g_ComponentTypes[name] = { iid: iid, ctor: ctor }; + g_ComponentTypes[name] = { "iid": iid, "ctor": ctor }; }; Engine.RegisterInterface = function(name) { - global["IID_"+name] = g_NewIID++; + global["IID_" + name] = g_NewIID++; }; Engine.RegisterMessageType = function(name) { - global["MT_"+name] = g_NewMTID++; + global["MT_" + name] = g_NewMTID++; }; Engine.QueryInterface = function(ent, iid) @@ -41,9 +41,9 @@ Engine.DestroyEntity = function(ent) { - for (var cid in g_Components[ent]) + for (let cid in g_Components[ent]) { - var cmp = g_Components[ent][cid]; + let cmp = g_Components[ent][cid]; if (cmp && cmp.Deinit) cmp.Deinit(); } @@ -85,9 +85,23 @@ global.ConstructComponent = function(ent, name, template) { - var cmp = new g_ComponentTypes[name].ctor(); - cmp.entity = ent; - cmp.template = template; + let cmp = new g_ComponentTypes[name].ctor(); + + Object.defineProperties(cmp, { + "entity": { + "value": ent, + "configurable": false, + "enumerable": false, + "writable": false + }, + "template": { + "value": template && deepfreeze(clone(template)), + "configurable": false, + "enumerable": false, + "writable": false + } + }); + cmp.Init(); if (!g_Components[ent]) Index: ps/trunk/binaries/data/mods/public/simulation/components/tests/setup_test.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/tests/setup_test.js +++ ps/trunk/binaries/data/mods/public/simulation/components/tests/setup_test.js @@ -0,0 +1,24 @@ +Engine.RegisterInterface("TestSetup"); + +function TestSetup() {}; +TestSetup.prototype.Init = function() {}; + +Engine.RegisterSystemComponentType(IID_TestSetup, "TestSetup", TestSetup); +let cmpTestSetup = ConstructComponent(SYSTEM_ENTITY, "TestSetup", { "property": "value" }); + +function expectException(func) +{ + try { + func(); + Engine.TS_FAIL("Missed exception at " + new Error().stack); + } catch (e) {} +} + +expectException(() => { cmpTestSetup.template = "replacement forbidden"; }); +expectException(() => { cmpTestSetup.template.property = "modification forbidden"; }); +expectException(() => { cmpTestSetup.template.other_property = "insertion forbidden"; }); +expectException(() => { delete cmpTestSetup.entity; }); +expectException(() => { delete cmpTestSetup.template; }); +expectException(() => { delete cmpTestSetup.template.property; }); + +TS_ASSERT_UNEVAL_EQUALS(cmpTestSetup.template, { "property": "value" }); Index: ps/trunk/binaries/data/mods/public/simulation/components/tests/test_Attack.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/tests/test_Attack.js +++ ps/trunk/binaries/data/mods/public/simulation/components/tests/test_Attack.js @@ -167,10 +167,6 @@ attackComponentTest(className, true, (attacker, cmpAttack, defender) => { TS_ASSERT_EQUALS(cmpAttack.GetBonusTemplate("Melee").BonusCav.Multiplier, 2); - // Check that we don't leak data - let bonus = cmpAttack.GetBonusTemplate("Melee"); - bonus.BonusCav.Multiplier = 2.7; - TS_ASSERT_EQUALS(cmpAttack.GetBonusTemplate("Melee").BonusCav.Multiplier, 2); TS_ASSERT(cmpAttack.GetBonusTemplate("Capture") === null); Index: ps/trunk/binaries/data/mods/public/simulation/components/tests/test_DeathDamage.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/tests/test_DeathDamage.js +++ ps/trunk/binaries/data/mods/public/simulation/components/tests/test_DeathDamage.js @@ -65,8 +65,10 @@ TS_ASSERT_UNEVAL_EQUALS(cmpDeathDamage.GetDeathDamageStrengths(), modifiedDamage); cmpDeathDamage.CauseDeathDamage(); +// Test splash damage bonus let splashBonus = { "BonusCav": { "Classes": "Cavalry", "Multiplier": 3 } }; -cmpDeathDamage.template.Bonuses = splashBonus; +template.Bonuses = splashBonus; +cmpDeathDamage = ConstructComponent(deadEnt, "DeathDamage", template); result.splashBonus = splashBonus; TS_ASSERT_UNEVAL_EQUALS(cmpDeathDamage.GetDeathDamageStrengths(), modifiedDamage); cmpDeathDamage.CauseDeathDamage(); Index: ps/trunk/binaries/data/mods/public/simulation/components/tests/test_GarrisonHolder.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/tests/test_GarrisonHolder.js +++ ps/trunk/binaries/data/mods/public/simulation/components/tests/test_GarrisonHolder.js @@ -133,8 +133,6 @@ TS_ASSERT_EQUALS(cmpGarrisonHolder.GetGarrisonedEntitiesCount(), 0); TS_ASSERT_EQUALS(cmpGarrisonHolder.CanPickup(unitToGarrisonId), false); -cmpGarrisonHolder.template.Pickup = true; -TS_ASSERT_EQUALS(cmpGarrisonHolder.CanPickup(unitToGarrisonId), true); TS_ASSERT_EQUALS(cmpGarrisonHolder.CanPickup(enemyUnitId), false); TS_ASSERT_EQUALS(cmpGarrisonHolder.IsFull(), false); TS_ASSERT_EQUALS(cmpGarrisonHolder.IsAllowedToGarrison(enemyUnitId), false); Index: ps/trunk/source/simulation2/components/tests/test_scripts.h =================================================================== --- ps/trunk/source/simulation2/components/tests/test_scripts.h +++ ps/trunk/source/simulation2/components/tests/test_scripts.h @@ -66,6 +66,7 @@ VfsPaths paths; TS_ASSERT_OK(vfs::GetPathnames(g_VFS, L"simulation/components/tests/", L"test_*.js", paths)); + paths.push_back(VfsPath(L"simulation/components/tests/setup_test.js")); for (const VfsPath& path : paths) { CSimContext context;