Repository navigation
feat(cli): add test-only offline playtest packaging - #131
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughThe CLI adds a test-only ChangesOffline playtest workflow
Stable Apps-in-Toss tooling
Estimated code review effort: 5 (Critical) | ~120 minutes Sequence Diagram(s)sequenceDiagram
participant Developer
participant CLI
participant WebPreview
participant OfflinePackager
participant FileSystem
Developer->>CLI: Run offline-playtest
CLI->>WebPreview: Read prepared web-preview metadata
CLI->>OfflinePackager: Pass artifact and output paths
OfflinePackager->>FileSystem: Bundle files and inline supported assets
OfflinePackager->>FileSystem: Write index.html, README, and evidence JSON
OfflinePackager-->>CLI: Return entry and evidence paths
CLI-->>Developer: Print test-only output details
Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (2)
packages/cli/src/offline-playtest.ts (2)
77-103: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueConsider adding common Phaser asset types to
mimeTypes.
readAssetDataUrlthrows for any extension that is absent from this map. Phaser games commonly ship.m4a,.opus,.fnt,.atlas,.glsl, and.gltf/.glbfiles. Those references fail packaging today. Add the common types, or keep the strict list and document the supported extension set in the limitations text.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/cli/src/offline-playtest.ts` around lines 77 - 103, Expand the mimeTypes map used by readAssetDataUrl to include the common Phaser asset extensions .m4a, .opus, .fnt, .atlas, .glsl, .gltf, and .glb with appropriate MIME types. Ensure these assets no longer trigger the unsupported-extension error during packaging.
718-720: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueEscape
quotebefore building the regular expression.
quotecurrently comes from a capture group limited to",', and`, sonew RegExp(quote, 'gu')is safe today. The call is fragile against a future change toliteralPattern. UseescapeRegExp(quote), or replace the regular expression withsplit(quote).join(...). This also removes the static-analysis warning.♻️ Proposed change
function escapeForQuote(value: string, quote: string): string { - return value.replace(/\\/gu, '\\\\').replace(new RegExp(quote, 'gu'), `\\${quote}`); + return value.replace(/\\/gu, '\\\\').replace(new RegExp(escapeRegExp(quote), 'gu'), `\\${quote}`); }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/cli/src/offline-playtest.ts` around lines 718 - 720, Update escapeForQuote to escape quote before using it to construct the regular expression, preferably via the existing escapeRegExp helper, or avoid dynamic regex construction with split/join. Preserve escaping of backslashes and quote characters while removing the static-analysis warning.Source: Linters/SAST tools
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/cli/src/offline-playtest.ts`:
- Around line 204-219: Update extractModuleEntry so inline script bodies are
also validated by assertSupportedBundledRuntime after the external module entry
is removed, or explicitly reject any remaining inline script elements. Ensure
new Worker usage in inline scripts cannot pass packaging while preserving
extraction of the single external module entry.
In `@README.md`:
- Around line 98-99: Update the README command output path from
artifacts/offline-playtest/index.html to
examples/phaser-starter/artifacts/offline-playtest/index.html, matching the game
root passed by the command and the actual generated file location.
---
Nitpick comments:
In `@packages/cli/src/offline-playtest.ts`:
- Around line 77-103: Expand the mimeTypes map used by readAssetDataUrl to
include the common Phaser asset extensions .m4a, .opus, .fnt, .atlas, .glsl,
.gltf, and .glb with appropriate MIME types. Ensure these assets no longer
trigger the unsupported-extension error during packaging.
- Around line 718-720: Update escapeForQuote to escape quote before using it to
construct the regular expression, preferably via the existing escapeRegExp
helper, or avoid dynamic regex construction with split/join. Preserve escaping
of backslashes and quote characters while removing the static-analysis warning.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: f84f5334-8841-4b08-9494-c4495de2e70a
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (10)
.sampo/changesets/offline-playtest-bundle.mdREADME.mddocs/GAME_DEVELOPMENT.mdpackage.jsonpackages/cli/package.jsonpackages/cli/src/index.tspackages/cli/src/offline-playtest.tspackages/cli/templates/phaser-game/README.mdpackages/cli/templates/phaser-game/docs/MPGD_KIT_WORKFLOWS.mdtools/smoke/cli-offline-playtest.ts
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c7ba4174e7
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2f5e37b901
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/cli/src/offline-playtest.ts`:
- Line 241: Update the script validation around
assertSupportedBundledRuntime(output) to match external script tags regardless
of whether their bodies are empty or contain fallback content, so every
src-based script is counted and rejected when not inlined. Add a smoke fixture
covering an external script with a non-whitespace fallback body.
- Around line 369-370: Replace raw CSS string matching and substitution in
packages/cli/src/offline-playtest.ts at lines 369-370 and 384-445 with CSS token
parsing: process only genuine CSS url tokens, detect and report only actual
`@import` at-keywords, and avoid matches inside strings, comments, or content
values. Update the smoke fixture in tools/smoke/cli-offline-playtest.ts at lines
108-121 and 243-255 to cover escaped `@import` tokens and text that must not be
rewritten.
In `@tools/validate-starter-workflow.ts`:
- Around line 789-798: The peer-rule check in the validator must verify the rule
within the YAML `peerDependencyRules.allowedVersions` mapping rather than using
`workspace.includes`. Update the validation around `expectedAitDevtoolsPeerRule`
to parse the workspace or scope matching to that specific mapping, so comments
and rules under other keys do not satisfy it; add a negative test covering a
commented or misplaced rule.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 764dceda-7e7d-4fe2-b5ee-23352aac302a
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (16)
.sampo/changesets/offline-playtest-bundle.mdREADME.mdadapters/ait/package.jsonadapters/ait/src/host.test.tsapps/target-ait/package.jsondocs/GAME_DEVELOPMENT.mddocs/ROADMAP_CHECKLIST.mdpackages/cli/src/offline-playtest.tspackages/cli/templates/phaser-game/README.mdpackages/cli/templates/phaser-game/apps/target-ait/package.jsonpackages/cli/templates/phaser-game/docs/MPGD_KIT_WORKFLOWS.mdpackages/cli/templates/phaser-game/package.jsonpackages/cli/templates/phaser-game/pnpm-workspace.yamlpnpm-workspace.yamltools/smoke/cli-offline-playtest.tstools/validate-starter-workflow.ts
🚧 Files skipped from review as they are similar to previous changes (4)
- README.md
- docs/GAME_DEVELOPMENT.md
- packages/cli/templates/phaser-game/docs/MPGD_KIT_WORKFLOWS.md
- packages/cli/templates/phaser-game/README.md
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 18fbff2b59
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ff284d4c6b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
|
@coderabbitai review |
|
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (2)
packages/cli/src/offline-playtest.ts (1)
1171-1178: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low valueConsider checking the asset size before base64 encoding.
readAssetDataUrlreads the whole asset and produces a base64 string. The total size check runs only after the final HTML is assembled. A single large asset therefore allocates the buffer, the base64 string, and the accumulated HTML before the limit rejects the run. A cheapstatSync(assetFile).sizecheck against the configured maximum fails earlier and keeps memory bounded.This is a test-only tool, so treat this as optional.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/cli/src/offline-playtest.ts` around lines 1171 - 1178, Optionally add an early asset-size guard in readAssetDataUrl using statSync(assetFile).size before readFileSync and base64 encoding. Compare the file size with the configured maximum and reject oversized assets before allocating their contents, while preserving the existing GLTF validation and data-URL flow for permitted assets.tools/smoke/cli-offline-playtest.ts (1)
349-361: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd a fixture for an asset directory whose name contains regex metacharacters.
The existing fixture uses the file name
sprite(2x).pnginside the plainassetsdirectory. Only directory names are interpolated into the literal pattern inpackages/cli/src/offline-playtest.ts, so this fixture does not exercise that path. A directory named for exampleassets(2x)currently produces an invalidRegExp. Add such a fixture to lock in the fix.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tools/smoke/cli-offline-playtest.ts` around lines 349 - 361, Add a smoke-playtest fixture alongside the existing parenthesizedCssHtml case using an asset directory name containing regex metacharacters, such as assets(2x), and place the CSS and referenced image under that directory. Assert the asset is inlined successfully, covering the directory interpolation path in packageAndReadFixture.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/cli/src/offline-playtest.ts`:
- Around line 416-422: Escape every entry in context.assetDirectories with the
existing escapeRegExp helper before joining them into assetDirectoryAlternative
in packages/cli/src/offline-playtest.ts#416-422. Add a smoke fixture in
tools/smoke/cli-offline-playtest.ts#349-361 using an asset directory such as
assets(2x), and assert that packaging succeeds and inlines the asset.
- Around line 464-471: Update isJavaScriptScriptType to strip the MIME parameter
portion after the first semicolon, trim the remaining essence, and compare that
normalized value against javascriptScriptTypes. Preserve the existing handling
for undefined or empty type values.
In `@tools/validate-starter-workflow.ts`:
- Around line 2117-2121: The allowedVersions parser in
validatePeerDependencyRuleParser must only scan nested entries when
allowedVersions is a mapping, not a scalar or block scalar. Track the value/node
type when entering allowedVersions, skip nested selector parsing for scalar
values such as allowedVersions: |, and add corresponding block-scalar invalid
cases to the existing invalid fixtures.
---
Nitpick comments:
In `@packages/cli/src/offline-playtest.ts`:
- Around line 1171-1178: Optionally add an early asset-size guard in
readAssetDataUrl using statSync(assetFile).size before readFileSync and base64
encoding. Compare the file size with the configured maximum and reject oversized
assets before allocating their contents, while preserving the existing GLTF
validation and data-URL flow for permitted assets.
In `@tools/smoke/cli-offline-playtest.ts`:
- Around line 349-361: Add a smoke-playtest fixture alongside the existing
parenthesizedCssHtml case using an asset directory name containing regex
metacharacters, such as assets(2x), and place the CSS and referenced image under
that directory. Assert the asset is inlined successfully, covering the directory
interpolation path in packageAndReadFixture.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 765764c3-29e3-429f-9079-b47b9e5619e3
📒 Files selected for processing (6)
.sampo/changesets/offline-playtest-bundle.mddocs/GAME_DEVELOPMENT.mdpackages/cli/src/offline-playtest.tspackages/cli/templates/phaser-game/README.mdtools/smoke/cli-offline-playtest.tstools/validate-starter-workflow.ts
🚧 Files skipped from review as they are similar to previous changes (3)
- .sampo/changesets/offline-playtest-bundle.md
- docs/GAME_DEVELOPMENT.md
- packages/cli/templates/phaser-game/README.md
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 55284462b2
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
|
@coderabbitai review |
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 20c1df9677
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@coderabbitai review |
|
@codex review |
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2f6c6199ee
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@coderabbitai review |
|
@codex review |
|
There was a problem hiding this comment.
🧹 Nitpick comments (1)
packages/cli/src/offline-playtest.ts (1)
305-316: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueSimplify the loop body.
The loop keeps an empty
ifbody and a trailing blank line. Invert the condition to remove the dead structure.♻️ Proposed simplification
for (const externalScript of externalScripts) { - if (externalScript === match) { - continue; - } - - if (!hasNoModuleAttribute(externalScript[2] ?? '')) { + if (externalScript !== match && !hasNoModuleAttribute(externalScript[2] ?? '')) { throw new Error( 'Offline playtest does not support additional external scripts beyond the module entry.', ); } - }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/cli/src/offline-playtest.ts` around lines 305 - 316, In the loop over externalScripts, invert the match condition so validation runs only when externalScript !== match, removing the empty continue branch and trailing blank line while preserving the existing hasNoModuleAttribute check and error behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@packages/cli/src/offline-playtest.ts`:
- Around line 305-316: In the loop over externalScripts, invert the match
condition so validation runs only when externalScript !== match, removing the
empty continue branch and trailing blank line while preserving the existing
hasNoModuleAttribute check and error behavior.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 1ca4e5b7-205b-4c24-b7fc-4753481fab43
📒 Files selected for processing (7)
README.mddocs/GAME_DEVELOPMENT.mdpackages/cli/src/offline-playtest.tspackages/cli/templates/phaser-game/README.mdpackages/cli/templates/phaser-game/docs/MPGD_KIT_WORKFLOWS.mdtools/smoke/cli-offline-playtest.tstools/validate-starter-workflow.ts
🚧 Files skipped from review as they are similar to previous changes (5)
- packages/cli/templates/phaser-game/docs/MPGD_KIT_WORKFLOWS.md
- packages/cli/templates/phaser-game/README.md
- README.md
- tools/validate-starter-workflow.ts
- docs/GAME_DEVELOPMENT.md
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2824416ae3
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
|
@coderabbitai review |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
base="38e6b42e4815ed77571ccc73bde5ad0fd5bc0711"
head="baac48f54e428e9750f735565c43abe414300491"
printf '%s\n' '--- requested revision and ancestry ---'
git rev-parse "$head"
git merge-base --is-ancestor "$base" "$head" &&
echo 'previous-reviewed-head-is-ancestor: yes' ||
echo 'previous-reviewed-head-is-ancestor: no'
git show --no-patch --format='%H%n%P%n%s%n%b' "$head"
git log --oneline "${base}..${head}"
git diff --no-ext-diff --name-status "${base}..${head}"
git diff --no-ext-diff --stat "${base}..${head}"
git diff --no-ext-diff --check "${base}..${head}"
printf '%s\n' '--- focused incremental patch ---'
git diff --no-ext-diff --unified=40 "${base}..${head}" -- \
packages/cli/src/offline-playtest.ts \
tools/smoke/cli-offline-playtest.ts
printf '%s\n' '--- affected implementation map ---'
ast-grep outline packages/cli/src/offline-playtest.ts \
--items all --type function \
--match 'timer|Timer|bind|Bind|callable|Callable|class|Class|heritage|Heritage|optional|Optional|native|Native|alias|Alias'
printf '%s\n' '--- timer binding, inheritance, optional call, and regression references ---'
rg -n -i -C 10 \
'\b(resolve|track|find|is|assert)[A-Za-z]*(?:Native|Callable|Alias|Binding|Timer|Class|Heritage)[A-Za-z]*\b|\
\b(setTimeout|setInterval|bind|call|apply|extends|super|optional|callback|native callable|class heritage)\b|\
\?\.\s*(?:\(|\[)|\?\.\s*[A-Za-z_$]|shadowed|member-owned' \
packages/cli/src/offline-playtest.ts \
tools/smoke/cli-offline-playtest.ts
printf '%s\n' '--- changed source contexts ---'
git diff --no-ext-diff --unified=0 "${base}..${head}" -- \
packages/cli/src/offline-playtest.ts \
tools/smoke/cli-offline-playtest.ts |
awk '
/^diff --git/ { file=$3; sub("^a/", "", file) }
/^@@/ && match($0, /\+([0-9]+)(,([0-9]+))?/, p) {
start=p[1]-35; if (start < 1) start=1
count=(p[3] ? p[3] : 1); end=p[1]+count+75
print file, start, end
}' |
sort -u |
while read -r file start end; do
printf "\n--- %s lines %s-%s ---\n" "$file" "$start" "$end"
sed -n "${start},${end}p" "$file" |
awk -v line="$start" '{ printf "%6d %s\n", line++, $0 }'
doneLength of output: 38412 🏁 Script executed: #!/bin/bash
set -euo pipefail
show_range() {
local file="$1" start="$2" end="$3"
printf '\n--- %s lines %s-%s ---\n' "$file" "$start" "$end"
sed -n "${start},${end}p" "$file" |
awk -v line="$start" '{ printf "%6d %s\n", line++, $0 }'
}
printf '%s\n' '--- callable validation and resolver ---'
show_range packages/cli/src/offline-playtest.ts 5370 6165
printf '%s\n' '--- runtime normalization and validation order ---'
show_range packages/cli/src/offline-playtest.ts 7350 7485
printf '%s\n' '--- timer and inheritance smoke tests ---'
show_range tools/smoke/cli-offline-playtest.ts 170 265
show_range tools/smoke/cli-offline-playtest.ts 2735 2840
printf '%s\n' '--- optional call and bind coverage ---'
rg -n -i -C 8 \
'optional.*(fetch|timer|bind|callable)|(?:fetch|setTimeout|setInterval|Function|Worker).*\?\.|\?\.?\s*\(' \
packages/cli/src/offline-playtest.ts \
tools/smoke/cli-offline-playtest.ts
printf '%s\n' '--- class heritage and timer binding references ---'
rg -n -i -C 8 \
'class.*extends|extends.*(?:Worker|Function|Base)|timer-bound-callback|bind\s*\(' \
packages/cli/src/offline-playtest.ts \
tools/smoke/cli-offline-playtest.ts
printf '%s\n' '--- diff check ---'
git diff --no-ext-diff --check \
38e6b42e4815ed77571ccc73bde5ad0fd5bc0711..baac48f54e428e9750f735565c43abe414300491Length of output: 116229
I found one issue.
const BackgroundWorker = class /* native worker base */ extends Worker {};
new BackgroundWorker("./worker.js");The expression does not match Use The timer bind callback-state handling is correct for the inspected cases. The class chain and named anonymous-class smoke cases cover the normal inheritance forms. The optional aliased native-fetch smoke case is present.
I completed a static review only. I did not run You are interacting with an AI system. |
|
@coderabbitai review Please review current PR HEAD |
|
@codex review Please review current PR HEAD |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
base="baac48f54e428e9750f735565c43abe414300491"
head="af2dfaaa90cd5d45e11e1352b594a090beb4c6b2"
printf '%s\n' '--- requested revision and ancestry ---'
git rev-parse "$head"
git merge-base --is-ancestor "$base" "$head" &&
echo 'previous-reviewed-head-is-ancestor: yes' ||
echo 'previous-reviewed-head-is-ancestor: no'
git show --no-patch --format='%H%n%P%n%s%n%b' "$head"
git log --oneline "${base}..${head}"
git diff --no-ext-diff --name-status "${base}..${head}"
git diff --no-ext-diff --stat "${base}..${head}"
git diff --no-ext-diff --check "${base}..${head}"
printf '%s\n' '--- focused incremental patch ---'
git diff --no-ext-diff --unified=45 "${base}..${head}" -- \
packages/cli/src/offline-playtest.ts \
tools/smoke/cli-offline-playtest.ts
printf '%s\n' '--- affected function map ---'
ast-grep outline packages/cli/src/offline-playtest.ts \
--items all --type function \
--match 'heritage|Heritage|class|Class|callable|Callable|native|Native|sequence|Sequence|parenthesized|Parenthesized'
printf '%s\n' '--- class heritage parser, callable resolver, normalizers, and regression cases ---'
rg -n -i -C 12 \
'\b(readNativeCallableClassHeritage|resolveNativeCallable|assertNoUnsupportedNativeCallables|normalizeStaticJavaScriptPropertyAccess|unwrapJavaScriptParenthesizedRange|findJavaScriptExpressionRange|findMatchingJavaScriptClosingParenthesis)\b|class\s+.*extends|extends\s*\(|extends.*[,)]|heritage|sequence|parenthes|callable class|optional.*call|timer.*bind' \
packages/cli/src/offline-playtest.ts \
tools/smoke/cli-offline-playtest.ts
printf '%s\n' '--- changed source contexts ---'
git diff --no-ext-diff --unified=0 "${base}..${head}" -- \
packages/cli/src/offline-playtest.ts \
tools/smoke/cli-offline-playtest.ts |
awk '
/^diff --git/ { file=$3; sub("^a/", "", file) }
/^@@/ && match($0, /\+([0-9]+)(,([0-9]+))?/, p) {
start=p[1]-35; if (start < 1) start=1
count=(p[3] ? p[3] : 1); end=p[1]+count+80
print file, start, end
}' |
sort -u |
while read -r file start end; do
printf "\n--- %s lines %s-%s ---\n" "$file" "$start" "$end"
sed -n "${start},${end}p" "$file" |
awk -v line="$start" '{ printf "%6d %s\n", line++, $0 }'
doneLength of output: 144949 🏁 Script executed: #!/bin/bash
set -euo pipefail
base="baac48f54e428e9750f735565c43abe414300491"
head="af2dfaaa90cd5d45e11e1352b594a090beb4c6b2"
printf '%s\n' '--- exact incremental patch ---'
git diff --no-ext-diff --unified=20 "${base}..${head}" -- \
packages/cli/src/offline-playtest.ts \
tools/smoke/cli-offline-playtest.ts
printf '%s\n' '--- heritage expression classification and body-boundary helpers ---'
sed -n '5738,5795p' packages/cli/src/offline-playtest.ts |
awk 'BEGIN { line=5738 } { printf "%6d %s\n", line++, $0 }'
sed -n '6048,6090p' packages/cli/src/offline-playtest.ts |
awk 'BEGIN { line=6048 } { printf "%6d %s\n", line++, $0 }'
rg -n -A90 -B8 \
'^function (findJavaScriptNamedExpressionBody|unwrapBalancedOuterParentheses|findSequenceExpressionLastValue)\b' \
packages/cli/src/offline-playtest.ts
printf '%s\n' '--- all class-heritage smoke cases and assertion helper ---'
sed -n '190,255p' tools/smoke/cli-offline-playtest.ts |
awk 'BEGIN { line=190 } { printf "%6d %s\n", line++, $0 }'
rg -n -A35 -B5 '^async function assertWorkerRejected\b|^function assertWorkerRejected\b' \
tools/smoke/cli-offline-playtest.ts
printf '%s\n' '--- whitespace check ---'
git diff --no-ext-diff --check "${base}..${head}"Length of output: 26042
The previous reviewed commit The class-heritage parser now reads the full heritage expression up to the class body. It supports trivia around The native callable resolver now handles:
The resolver propagates the native The added smoke tests cover both parenthesized and sequence Worker heritage cases.
I found no new actionable issue in the reviewed changes. I completed a static review only. I did not run You are interacting with an AI system. |
|
Addressed the CodeRabbit finding from |
|
@codex review Please review final current PR HEAD |
|
@coderabbitai review Please review final current PR HEAD |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
base="af2dfaaa90cd5d45e11e1352b594a090beb4c6b2"
head="fec715c47d0accf55a01874a57747d45485e3696"
printf '%s\n' '--- requested revision and ancestry ---'
git rev-parse "$head"
git merge-base --is-ancestor "$base" "$head" &&
echo 'previous-reviewed-head-is-ancestor: yes' ||
echo 'previous-reviewed-head-is-ancestor: no'
git show --no-patch --format='%H%n%P%n%s%n%b' "$head"
git log --oneline "${base}..${head}"
git diff --no-ext-diff --stat "${base}..${head}"
git diff --no-ext-diff --name-status "${base}..${head}"
git diff --no-ext-diff --check "${base}..${head}"
printf '%s\n' '--- focused incremental patch ---'
git diff --no-ext-diff --unified=45 "${base}..${head}" -- \
packages/cli/src/offline-playtest.ts \
tools/smoke/cli-offline-playtest.ts
printf '%s\n' '--- affected function map ---'
ast-grep outline packages/cli/src/offline-playtest.ts \
--items all --type function \
--match 'heritage|Heritage|class|Class|callable|Callable|native|Native|trivia|Trivia'
printf '%s\n' '--- parser, callable propagation, and regression references ---'
rg -n -i -C 12 \
'\b(readNativeCallableClassHeritage|resolveNativeCallable|assertNoUnsupportedNativeCallables|javascriptTriviaPatternSource|findJavaScriptNamedExpressionBody|findSequenceExpressionLastValue|unwrapBalancedOuterParentheses)\b|class\s*/\*|extends\s+Worker|comment-trivia|heritage|anonymous-class' \
packages/cli/src/offline-playtest.ts \
tools/smoke/cli-offline-playtest.ts
printf '%s\n' '--- exact relevant source regions ---'
sed -n '5715,5815p' packages/cli/src/offline-playtest.ts |
awk 'BEGIN { line=5715 } { printf "%6d %s\n", line++, $0 }'
sed -n '6025,6115p' packages/cli/src/offline-playtest.ts |
awk 'BEGIN { line=6025 } { printf "%6d %s\n", line++, $0 }'
rg -n -A35 -B8 \
'anonymous.*comment|comment.*trivia|native worker base|class /\*' \
tools/smoke/cli-offline-playtest.tsLength of output: 70236
The previous reviewed commit The incremental commit adds the exact comment-trivia regression fixture: const BackgroundWorker = class /* retained trivia */ extends /* native base */ Worker {};
new BackgroundWorker("./worker.js");
The callable resolver extracts
I found no new actionable issue in the reviewed change. I completed a static review only. I did not run You are interacting with an AI system. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: fec715c47d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@coderabbitai review Please review current PR HEAD |
|
@codex review Please review current PR HEAD |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
base="fec715c47d0accf55a01874a57747d45485e3696"
head="8fb8b97a3369647d94e9da85b5cc5aee31c98f8b"
printf '%s\n' '--- requested revision and ancestry ---'
git rev-parse "$head"
git merge-base --is-ancestor "$base" "$head" &&
echo 'previous-reviewed-head-is-ancestor: yes' ||
echo 'previous-reviewed-head-is-ancestor: no'
git show --no-patch --format='%H%n%P%n%s%n%b' "$head"
git log --oneline "${base}..${head}"
git diff --no-ext-diff --name-status "${base}..${head}"
git diff --no-ext-diff --stat "${base}..${head}"
git diff --no-ext-diff --check "${base}..${head}"
printf '%s\n' '--- focused incremental patch ---'
git diff --no-ext-diff --unified=35 "${base}..${head}" -- \
packages/cli/src/offline-playtest.ts \
tools/smoke/cli-offline-playtest.ts
printf '%s\n' '--- affected implementation map ---'
ast-grep outline packages/cli/src/offline-playtest.ts \
--items all --type function \
--match 'class|Class|heritage|Heritage|bind|Bind|call|Call|script|Script|raw|Raw|html|Html|svg|Svg|native|Native'
printf '%s\n' '--- parser, validator, and regression references ---'
rg -n -i -C 12 \
'\b(readNativeCallableClassHeritage|resolveNativeCallable|assertNoUnsupportedNativeCallables|\
findJavaScript.*Argument|bind.*call|call.*bind|\
assertNo.*Script|dynamic.*(?:html|svg|script)|raw.*text|end.tag|\
parse.*(?:html|svg)|javascriptTriviaPatternSource)\b|\
class.*extends|\.bind\s*\(|\.call\s*\(|createElement|innerHTML|outerHTML|insertAdjacentHTML|\
<svg|<script|</script' \
packages/cli/src/offline-playtest.ts \
tools/smoke/cli-offline-playtest.ts
printf '%s\n' '--- changed source contexts ---'
git diff --no-ext-diff --unified=0 "${base}..${head}" -- \
packages/cli/src/offline-playtest.ts \
tools/smoke/cli-offline-playtest.ts |
awk '
/^diff --git/ { file=$3; sub("^a/", "", file) }
/^@@/ && match($0, /\+([0-9]+)(,([0-9]+))?/, p) {
start=p[1]-35; if (start < 1) start=1
count=(p[3] ? p[3] : 1); end=p[1]+count+80
print file, start, end
}' |
sort -u |
while read -r file start end; do
printf "\n--- %s lines %s-%s ---\n" "$file" "$start" "$end"
sed -n "${start},${end}p" "$file" |
awk -v line="$start" '{ printf "%6d %s\n", line++, $0 }'
doneLength of output: 59519 🏁 Script executed: #!/bin/bash
set -euo pipefail
show_range() {
local file="$1" start="$2" end="$3"
printf '\n--- %s lines %s-%s ---\n' "$file" "$start" "$end"
sed -n "${start},${end}p" "$file" |
awk -v line="$start" '{ printf "%6d %s\n", line++, $0 }'
}
printf '%s\n' '--- raw-text parsing and HTML consumers ---'
show_range packages/cli/src/offline-playtest.ts 620 835
show_range packages/cli/src/offline-playtest.ts 4950 5075
show_range packages/cli/src/offline-playtest.ts 5150 5348
printf '%s\n' '--- native callable resolution and class heritage rejection ---'
show_range packages/cli/src/offline-playtest.ts 5400 5750
show_range packages/cli/src/offline-playtest.ts 5970 6235
printf '%s\n' '--- dynamic-element validation and runtime guard assembly ---'
show_range packages/cli/src/offline-playtest.ts 5340 5405
show_range packages/cli/src/offline-playtest.ts 6235 6335
printf '%s\n' '--- exact smoke-test contexts ---'
show_range tools/smoke/cli-offline-playtest.ts 185 255
show_range tools/smoke/cli-offline-playtest.ts 720 815
show_range tools/smoke/cli-offline-playtest.ts 945 1010
show_range tools/smoke/cli-offline-playtest.ts 2780 2870
printf '%s\n' '--- focused references ---'
rg -n -i -C 6 \
'findNativeCallableClassHeritages|readNativeCallableClassHeritage|deriveBoundNativeCallableKinds|readBoundNativeCallableExpression|createHtmlRawTextPattern|transformOutsideHtmlRawText|maskHtmlRawTextBodies|dynamically created script|blockedTag|nested-bind-call|attributed-script-end|property-stored-worker' \
packages/cli/src/offline-playtest.ts \
tools/smoke/cli-offline-playtest.ts
printf '%s\n' '--- full incremental diff integrity ---'
git diff --no-ext-diff --check \
fec715c47d0accf55a01874a57747d45485e3696..8fb8b97a3369647d94e9da85b5cc5aee31c98f8bLength of output: 111764
I found one issue.
(namespace===undefined||String(namespace).toLowerCase()==='http://www.w3.org/1999/xhtml')
&& ['meta','object','embed','script'].includes(...)Therefore, document.createElementNS("http://www.w3.org/2000/svg", "script");The static validator rejects the direct form. However, it cannot reject all runtime-computed tag or namespace values. An SVG Apply the HTML-namespace restriction only to The incremental change correctly adds:
I completed a static review only. I did not run You are interacting with an AI system. |
|
Addressed the remaining SVG runtime bypass in d14db81. |
|
/coderabbitai review d14db81 |
|
/codex review d14db81 |
|
@codex review Please review exact current PR HEAD |
|
@coderabbitai review Please review exact current PR HEAD |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
base="8fb8b97a3369647d94e9da85b5cc5aee31c98f8b"
head="d14db813ce066cd1e2a462cd4eb366b2e91a6190"
printf '%s\n' '--- revision and ancestry ---'
git rev-parse "$head"
git merge-base --is-ancestor "$base" "$head" && echo 'previous-reviewed-head-is-ancestor: yes' || echo 'previous-reviewed-head-is-ancestor: no'
git show --no-patch --format='%H%n%P%n%s%n%b' "$head"
git log --oneline "${base}..${head}"
git diff --no-ext-diff --name-status "${base}..${head}"
git diff --no-ext-diff --stat "${base}..${head}"
git diff --no-ext-diff --check "${base}..${head}"
printf '%s\n' '--- incremental patch ---'
git diff --no-ext-diff --unified=45 "${base}..${head}" -- \
packages/cli/src/offline-playtest.ts \
tools/smoke/cli-offline-playtest.ts
printf '%s\n' '--- relevant implementation map ---'
ast-grep outline packages/cli/src/offline-playtest.ts \
--items all --type function \
--match 'render|Render|runtime|Runtime|guard|Guard|element|Element|script|Script'
printf '%s\n' '--- runtime guard and regression references ---'
rg -n -i -C 12 \
'\b(renderOfflineRuntimeGuard|blockedTag|createElementNS|createElement|vm|runIn|context|svg|script|namespace)\b' \
packages/cli/src/offline-playtest.ts \
tools/smoke/cli-offline-playtest.ts
printf '%s\n' '--- changed source contexts ---'
git diff --no-ext-diff --unified=0 "${base}..${head}" -- \
packages/cli/src/offline-playtest.ts \
tools/smoke/cli-offline-playtest.ts |
awk '
/^diff --git/ { file=$3; sub("^a/", "", file) }
/^@@/ && match($0, /\+([0-9]+)(,([0-9]+))?/, p) {
start=p[1]-30; if (start < 1) start=1
count=(p[3] ? p[3] : 1); end=p[1]+count+70
print file, start, end
}' |
sort -u |
while read -r file start end; do
printf "\n--- %s lines %s-%s ---\n" "$file" "$start" "$end"
sed -n "${start},${end}p" "$file" |
awk -v line="$start" '{ printf "%6d %s\n", line++, $0 }'
doneLength of output: 202191
The previous reviewed commit The runtime guard now rejects The guard keeps the HTML-namespace restriction for The VM regression extracts the generated guard from the packaged HTML. It executes the guard. It verifies that this call throws: document.createElementNS("http://www.w3.org/2000/svg", "script")This resolves the prior SVG namespace bypass.
I found no new actionable issue in the reviewed change. I completed a static review only. I did not run If you found this review helpful, would you consider giving us a shout-out on X? Thank you for using CodeRabbit! You are interacting with an AI system. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d14db813ce
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
Implemented the six exact-head findings in c328579 as a category-wide hardening pass (qualified DOM names, evaluator invocation forms, native style receivers, markup sinks, reflective workers, and all navigation setters). Full @coderabbitai review |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
base="d14db813ce066cd1e2a462cd4eb366b2e91a6190"
printf '%s\n' '--- PR head and ancestry ---'
git rev-parse HEAD
git merge-base --is-ancestor "$base" HEAD &&
echo 'previous-reviewed-head-is-ancestor: yes' ||
echo 'previous-reviewed-head-is-ancestor: no'
git show --no-patch --format='%H%n%P%n%s%n%b' HEAD
git log --oneline "${base}..HEAD"
printf '%s\n' '--- changed paths and patch integrity ---'
git diff --no-ext-diff --name-status "${base}..HEAD"
git diff --no-ext-diff --stat "${base}..HEAD"
git diff --no-ext-diff --check "${base}..HEAD"
printf '%s\n' '--- focused incremental patch ---'
git diff --no-ext-diff --unified=32 "${base}..HEAD" -- \
packages/cli/src/offline-playtest.ts \
tools/smoke/cli-offline-playtest.ts
printf '%s\n' '--- relevant function outline ---'
ast-grep outline packages/cli/src/offline-playtest.ts \
--items all --type function \
--match 'dom|Dom|style|Style|markup|Markup|html|Html|worker|Worker|navigation|Navigation|location|Location|evaluator|Evaluator|runtime|Runtime|guard|Guard'
printf '%s\n' '--- implementation and regression references ---'
rg -n -i -C 10 \
'\b(renderOfflineRuntimeGuard|assertSupportedBundledRuntime|assertNoUnsupportedNativeCallables|\
createElement(?:NS)?|innerHTML|outerHTML|insertAdjacentHTML|cssText|setProperty|\
Worker|SharedWorker|Reflect|eval|Function|setTimeout|setInterval|location|assign|replace|href|\
navigation|qualified|style|markup)\b' \
packages/cli/src/offline-playtest.ts \
tools/smoke/cli-offline-playtest.tsLength of output: 77519 🏁 Script executed: #!/bin/bash
set -euo pipefail
show_range() {
local file="$1"
local start="$2"
local end="$3"
printf '\n--- %s lines %s-%s ---\n' "$file" "$start" "$end"
sed -n "${start},${end}p" "$file" |
awk -v line="$start" '{ printf "%6d %s\n", line++, $0 }'
}
printf '%s\n' '--- runtime guard and bundled-runtime validation ---'
show_range packages/cli/src/offline-playtest.ts 5350 5725
printf '%s\n' '--- native callable classification and reflective invocation validation ---'
show_range packages/cli/src/offline-playtest.ts 5725 6255
printf '%s\n' '--- dynamic DOM, markup, and native document-element validation ---'
show_range packages/cli/src/offline-playtest.ts 6255 6715
printf '%s\n' '--- worker and navigation validation ---'
show_range packages/cli/src/offline-playtest.ts 6815 7355
printf '%s\n' '--- new smoke-test fixtures, including runtime guard execution ---'
sed -n '1,150p;230,420p;850,1030p;2120,2210p;2925,3025p' \
tools/smoke/cli-offline-playtest.ts |
awk '{ printf "%6d %s\n", NR, $0 }'
printf '%s\n' '--- focused implementation and regression references ---'
rg -n -i -C 5 \
'renderOfflineRuntimeHardeningGuard|assertNoUnsafeMarkupInjection|isNativeDocumentElementExpression|\
Reflect\.(apply|construct)|native-document-style|markup|svg:script|\
location-(host|hostname|pathname|port|protocol|search)|optional-(eval|function)|indirect-sequence-eval' \
packages/cli/src/offline-playtest.ts \
tools/smoke/cli-offline-playtest.tsLength of output: 120311
The previous reviewed commit The incremental changes address the stated categories:
The smoke suite includes static and VM-executed regressions for these paths. The member-owned markup and style cases remain permitted.
I found no new actionable issue in the reviewed changes. I completed a static review only. I did not independently run You are interacting with an AI system. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c328579b2d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| } | ||
|
|
||
| function renderOfflineRuntimeHardeningGuard(): string { | ||
| return `(()=>{const denied=(api,value)=>new TypeError('[mpgd offline playtest] '+api+' blocked network access: '+String(value));const localName=(name)=>String(name).toLowerCase().split(':').at(-1);if(globalThis.Document){for(const methodName of ['createElement','createElementNS']){const method=Document.prototype[methodName];if(typeof method==='function'){Document.prototype[methodName]=function(...args){const name=args[methodName==='createElementNS'?1:0];if(localName(name)==='script')throw denied('document.'+methodName,name);return method.apply(this,args)}}}}const blockMarkup=(prototype)=>{if(!prototype)return;for(const property of ['innerHTML','outerHTML']){const descriptor=Object.getOwnPropertyDescriptor(prototype,property);if(descriptor?.set){try{Object.defineProperty(prototype,property,{...descriptor,set(value){throw denied(property,value)}})}catch{}}}for(const methodName of ['insertAdjacentHTML','setHTML','setHTMLUnsafe']){if(typeof prototype[methodName]==='function'){try{Object.defineProperty(prototype,methodName,{configurable:true,writable:true,value:(...args)=>{throw denied(methodName,args.at(-1))}})}catch{}}}};blockMarkup(globalThis.Element?.prototype);blockMarkup(globalThis.ShadowRoot?.prototype);if(globalThis.Range?.prototype&&typeof Range.prototype.createContextualFragment==='function'){try{Object.defineProperty(Range.prototype,'createContextualFragment',{configurable:true,writable:true,value:(value)=>{throw denied('Range.createContextualFragment',value)}})}catch{}}for(const name of ['Worker','SharedWorker']){const Native=globalThis[name];if(typeof Native==='function'){try{globalThis[name]=new Proxy(Native,{construct(_target,args){throw denied(name,args[0])}})}catch{}}}if(globalThis.Location){for(const property of ['href','host','hostname','pathname','port','protocol','search']){const descriptor=Object.getOwnPropertyDescriptor(Location.prototype,property);if(descriptor?.set){try{Object.defineProperty(Location.prototype,property,{...descriptor,set(value){throw denied('location.'+property,value)}})}catch{}}}}})();`; |
There was a problem hiding this comment.
Reject runtime-installed string event handlers
When retained code calls document.body.setAttribute("onclick", "window.location='https://example.com'"), the handler body remains hidden inside a string and passes bundled-runtime navigation validation. The CSP explicitly permits inline script, the runtime guards do not wrap setAttribute, and the click guard only rejects non-fragment anchors, so clicking a non-anchor descendant executes the handler and navigates away from an artifact claiming to block script-driven navigation. Reject native on* attribute writes just as source HTML event-handler attributes are rejected.
Useful? React with 👍 / 👎.
| if (target === undefined || property !== 'href') { | ||
| continue; |
There was a problem hiding this comment.
Cover every Location setter in descriptor checks
This check only rejects a descriptor lookup when the property is exactly href, so Object.getOwnPropertyDescriptor(location, "pathname").set.call(location, "/escape") passes validation and invokes the native navigation setter without matching a direct Location assignment. Location navigation attributes are legacy-unforgeable own properties, so the attempted Location.prototype setter replacement does not protect this path; include all newly covered navigation attributes here rather than retaining the href-only condition.
Useful? React with 👍 / 👎.
| if (css === undefined) { | ||
| return; |
There was a problem hiding this comment.
Reject unresolved resource-bearing style values
When a proven native receiver uses a runtime-computed resource value, such as document.body.style.backgroundImage = url("/assets/${theme}.png")``, static resolution returns undefined and this branch silently preserves the assignment. The generated direct-file CSP permits images only from `data:` or `blob:`, so the artifact packages successfully but the background fails at runtime; reject unresolved values for resource-bearing CSS properties while continuing to allow dynamic non-resource properties such as `color`.
Useful? React with 👍 / 👎.
| const loaderPattern = new RegExp( | ||
| `(?<![$.\\u200C\\u200D\\p{ID_Continue}])(${javascriptIdentifierPatternSource})\\s*\\.\\s*load\\s*\\.\\s*(${loaderMethods})\\s*\\(`, | ||
| 'gu', |
There was a problem hiding this comment.
Trace bound Phaser loader methods
When application code binds a proven loader method, for example const loadImage = scene.load.image.bind(scene.load); loadImage("hero", "/assets/pixel.png"), this direct receiver.load.method(...) pattern never marks the URL argument for inlining. The artifact therefore retains the local path, and Phaser's eventual XHR is rejected by the generated runtime guard because only data: and blob: URLs are allowed; propagate proven Phaser loader provenance through bind and aliases or reject such retained calls during packaging.
Useful? React with 👍 / 👎.
Summary
mpgd game offline-playtest <game>for packaging an existingweb-previewartifact into one direct-file HTML test bundlempgd.targets.json, release manifests, PWA/deployment flows, and store-submission artifactsfile://storage limitations in kit and generated-game guides@mpgd/climinor Sampo changesetVerification
pnpm checkpnpm testpnpm smoke:cli-offline-playtestpnpm build:packagespnpm pack:packages:preparedocr review --commit deb9f6f(6 findings; all patched)ocr review --commit c7ba417(0 findings)pnpm sampo:release:dry-runis intentionally branch-gated and reported that releases are allowed only frommain.Scope boundary
This is test-play tooling only. It does not claim full offline support for a game and does not create a new distribution target. Server-backed identity, purchases, ads, reward grants, leaderboards, and cloud saves remain unavailable unless the game supplies its own disabled/local fallback.
Summary by CodeRabbit
New Features
mpgd game offline-playtestto create self-contained, network-blocked browser test copies from web previews.Documentation
Tests
Maintenance