diff --git a/assets/custom/Json/level2060.json.meta b/assets/custom/Json/level2060.json.meta new file mode 100644 index 00000000..7b05e3d0 --- /dev/null +++ b/assets/custom/Json/level2060.json.meta @@ -0,0 +1,6 @@ +{ + "ver": "1.0.2", + "uuid": "5f7a5510-f770-43bd-9389-91eba6e1d7a2", + "importer": "json", + "subMetas": {} +} \ No newline at end of file diff --git a/build-templates/wechatgame/game.js b/build-templates/wechatgame/game.js index dabcdd25..3797a4b8 100644 --- a/build-templates/wechatgame/game.js +++ b/build-templates/wechatgame/game.js @@ -1,6 +1,8 @@ "use strict"; -const memoryDiagnostics = require('./memory-diagnostics').create(wx, require('./memory-diagnostics-build')); +// Opt in only when collecting diagnostics; release builds remain disabled. +const MEMORY_DIAGNOSTICS_ENABLED = false; +const memoryDiagnostics = require('./memory-diagnostics').create(wx, require('./memory-diagnostics-build'), MEMORY_DIAGNOSTICS_ENABLED); memoryDiagnostics.beforeBoot(startGame); function startGame() { diff --git a/build-templates/wechatgame/memory-diagnostics.js b/build-templates/wechatgame/memory-diagnostics.js index ecd35930..ee6f81df 100644 --- a/build-templates/wechatgame/memory-diagnostics.js +++ b/build-templates/wechatgame/memory-diagnostics.js @@ -7,7 +7,8 @@ const UPLOAD_URL = 'https://sor779u2w8.sealoshzh.site/memoryDiagnostics'; const FILE = /^(\d{13}-[a-z0-9]{8})\.(start|0|1)\.jsonl$/; const noop = { enabled: false, record() {}, attachEngine() {}, beforeBoot(next) { next(); }, exportPrevious(next) { if (next) next(); } }; -function create(wx, build) { +function create(wx, build, enabled = false) { + if (enabled !== true) return noop; build = build || {}; let account; try { account = wx.getAccountInfoSync().miniProgram; } catch (_) { return noop; } diff --git a/tools/test-memory-diagnostics.cjs b/tools/test-memory-diagnostics.cjs index 1060c375..2030df40 100644 --- a/tools/test-memory-diagnostics.cjs +++ b/tools/test-memory-diagnostics.cjs @@ -2,7 +2,7 @@ const test = require('node:test'), assert = require('node:assert/strict'); const fs = require('node:fs'), vm = require('node:vm'); const source = fs.readFileSync('build-templates/wechatgame/memory-diagnostics.js', 'utf8'); const ROOT = '/user/memory-diagnostics/'; -function fixture(files = new Map(), envVersion = 'trial', now = 1800000000000, initiallyFull = false) { +function fixture(files = new Map(), envVersion = 'trial', now = 1800000000000, initiallyFull = false, enabled = true) { const handlers = {}, timers = [], modals = [], sheets = [], calls = [], logins = [], requests = [], timeouts = new Map(); let timeoutId = 0; let failWrite = initiallyFull; @@ -30,7 +30,7 @@ function fixture(files = new Map(), envVersion = 'trial', now = 1800000000000, i const module = { exports: {} }; vm.runInNewContext(source, { module, Date: Clock, setInterval: fn => { timers.push(fn); return timers.length; }, clearInterval: id => { timers[id - 1] = null; }, setTimeout: fn => { timeouts.set(++timeoutId, fn); return timeoutId; }, clearTimeout: id => timeouts.delete(id) }); - const api = module.exports.create(wx, { id: 'build-123', builtAt: '2026-10-26', flags: { iOSHighPerformance: true, 'iOSHighPerformance+': true } }); + const api = module.exports.create(wx, { id: 'build-123', builtAt: '2026-10-26', flags: { iOSHighPerformance: true, 'iOSHighPerformance+': true } }, enabled); const rows = () => [...files.values()].flatMap(s => s.split('\n').filter(Boolean).flatMap(line => { try { return [JSON.parse(line)]; } catch (_) { return []; } })); return { api, wx, files, handlers, timers, modals, sheets, calls, rows, logins, requests, timeouts, full() { failWrite = true; }, advance(ms) { now += ms; }, tick() { now += 5000; timers.filter(Boolean).forEach(fn => fn()); } }; @@ -66,6 +66,28 @@ function fakeEngine() { Director: { EVENT_BEFORE_SCENE_LOADING: 'load', EVENT_BEFORE_SCENE_LAUNCH: 'before', EVENT_AFTER_SCENE_LAUNCH: 'after', EVENT_AFTER_UPDATE: 'frame' }, find: () => null }; return { cc, events, calls, Bundle }; } +test('diagnostics default to off before accessing WeChat APIs', () => { + const module = { exports: {} }; + vm.runInNewContext(source, { module }); + const wx = new Proxy({}, { get() { throw Error('WeChat API accessed while disabled'); } }); + for (const enabled of [undefined, false, null, 0, 1, 'true']) { + assert.equal(module.exports.create(wx, {}, enabled).enabled, false); + } + assert.equal(module.exports.create(wx).enabled, false); +}); +test('master switch disables diagnostics in every channel without side effects', () => { + for (const env of ['develop', 'trial', 'release']) { + const files = new Map([[ROOT + '1800000000000-abcdefgh.start.jsonl', '{"event":"session.start"}\n']]); + const before = [...files]; + const f = fixture(files, env, 1800000010000, false, false), e = fakeEngine(), original = e.Bundle.prototype.load; + let launched = 0, exported = 0; + f.api.attachEngine(e.cc); f.api.record('x'); f.api.beforeBoot(() => launched++); f.api.exportPrevious(() => exported++); + assert.equal(f.api.enabled, false); assert.equal(launched, 1); assert.equal(exported, 1); + assert.equal(e.Bundle.prototype.load, original); assert.deepEqual([...files], before); + for (const entries of [f.calls, f.timers, f.modals, f.sheets, f.logins, f.requests, Object.keys(f.handlers), Object.keys(e.events)]) assert.equal(entries.length, 0); + assert.equal(f.timeouts.size, 0); + } +}); test('release/unknown/unavailable channel performs no persistence, listeners, timers or engine patching', () => { for (const env of ['release', null, 'unknown', 'throws']) { const f = fixture(new Map(), env), e = fakeEngine(), original = e.Bundle.prototype.load; @@ -349,7 +371,10 @@ test('bootstrap keeps the recovery prompt before adapter/engine initialization a const boot = fs.readFileSync('build-templates/wechatgame/game.js', 'utf8'); const calls = [], context = { wx: {}, window: { boot: () => calls.push('boot') }, cc: { view: {}, sys: { platform: 1, WECHAT_GAME_SUB: 2 }, macro: {} }, requirePlugin: () => calls.push('engine'), __globalAdapter: { init() {}, adaptEngine() {} }, - require: name => name === './memory-diagnostics' ? { create: () => ({ enabled: false, beforeBoot: next => { context.resume = next; }, attachEngine() {} }) } : {} }; + require: name => name === './memory-diagnostics' ? { create: (wx, build, enabled) => { + assert.equal(enabled, false); + return { enabled: false, beforeBoot: next => { context.resume = next; }, attachEngine() {} }; + } } : {} }; vm.runInNewContext(boot, context); assert.deepEqual(calls, []); context.resume(); assert.deepEqual(calls, ['engine', 'boot']); assert(boot.includes('window.boot();')); });