function evalWithCache(code, ctx) { ctx = ctx || {}; ctx = Object.create(ctx, { fileName: { value: "evalWithCacheCode.js" }, lineNumber: { value: 0 } }); code = code instanceof Object ? code : cacheEntry(code); var incremental = ctx.incremental || false; // We create a new global ... if (!("global" in ctx)) ctx.global = newGlobal({newCompartment: ctx.newCompartment}); // NOTE: Run-once scripts must use incremental mode since they may use // singleton objects that are mutated by the time the bytecode is captured in // non-incremental mode. if (!("isRunOnce" in ctx)) ctx.isRunOnce = incremental; var ctx_save; if (incremental) ctx_save = Object.create(ctx, {saveIncrementalBytecode: { value: true } }); else ctx_save = Object.create(ctx, {saveBytecode: { value: true } }); // Fetch the verification function from the evaluation context. This function // is used to assert the state of the script/function after each run of the // evaluate function. var checkAfter = ctx.checkAfter || function(ctx) {}; // The generation counter is used to represent environment variations which // might cause the program to run differently, and thus to have a different // set of functions executed. ctx.global.generation = 0; var res1 = evaluate(code, ctx_save); checkAfter(ctx); ctx.global.generation = 1; var res2 = evaluate(code, Object.create(ctx_save, {loadBytecode: { value: true } })); checkAfter(ctx); ctx.global.generation = 2; var res3 = evaluate(code, Object.create(ctx, {loadBytecode: { value: true } })); checkAfter(ctx); ctx.global.generation = 3; var res0 = evaluate(code, ctx); checkAfter(ctx); if (ctx.assertEqResult) { assertEq(res0, res1); assertEq(res0, res2); assertEq(res0, res3); } if (ctx.checkFrozen) { assertEq(Object.isFrozen(res0), Object.isFrozen(res1)); assertEq(Object.isFrozen(res0), Object.isFrozen(res2)); assertEq(Object.isFrozen(res0), Object.isFrozen(res3)); } }