fix(plugins): validate example panel reply dispatch (#31877)

* fix(plugins): validate example panel reply dispatch

* style(plugins): brace panel reply admission guard
This commit is contained in:
Neil
2026-10-22 00:19:10 -07:00
committed by GitHub
parent 95f8f73b9a
commit 9e1ffb2333
2 changed files with 68 additions and 5 deletions
+7 -5
View File
@@ -51,14 +51,14 @@
<script>
'use strict'
var seq = 0
var pending = {}
var pending = new Map()
var statusEl = document.getElementById('status')
var termsEl = document.getElementById('terms')
function call(action, params) {
return new Promise(function (resolve) {
var requestId = 'req-' + ++seq
pending[requestId] = resolve
pending.set(requestId, resolve)
// The panel frame is an opaque origin, so '*' is the only usable
// targetOrigin; the host verifies the sending window instead.
window.parent.postMessage(
@@ -70,10 +70,12 @@
window.addEventListener('message', function (event) {
var data = event.data
if (!data || data.type !== 'orca-panel-action-result') return
var resolve = pending[data.requestId]
if (event.source !== window.parent || !data || data.type !== 'orca-panel-action-result') {
return
}
var resolve = pending.get(data.requestId)
if (!resolve) return
delete pending[data.requestId]
pending.delete(data.requestId)
resolve(data)
})
@@ -0,0 +1,61 @@
import { readFileSync } from 'node:fs'
import { createContext, runInContext } from 'node:vm'
import { describe, expect, it, vi } from 'vitest'
describe('hello-orca panel replies', () => {
it('only resolves an outstanding request once, from the parent window', async () => {
const parent = { postMessage: vi.fn() }
let receive: (event: { source: unknown; data: unknown }) => void = () => {
throw new Error('Panel did not register its message listener')
}
const context = createContext({
window: {
parent,
addEventListener: (name: string, listener: typeof receive) => {
if (name === 'message') {
receive = listener
}
}
},
document: { getElementById: () => ({ addEventListener: vi.fn() }) }
})
const html = readFileSync(
new URL('../../../examples/plugins/hello-orca/panel.html', import.meta.url),
'utf8'
)
const script = html.match(/<script>([\s\S]*?)<\/script>/)?.[1]
if (!script) {
throw new Error('Panel script missing')
}
runInContext(script, context)
const resolved = vi.fn()
const request = runInContext("call('workspace.readContext')", context).then(resolved)
const reply = {
type: 'orca-panel-action-result',
requestId: 'req-1',
ok: true,
value: null
}
for (const requestId of ['__proto__', 'constructor', '__defineGetter__', 'unknown']) {
expect(() => receive({ source: parent, data: { ...reply, requestId } })).not.toThrow()
}
receive({ source: {}, data: reply })
await Promise.resolve()
expect(resolved).not.toHaveBeenCalled()
receive({ source: parent, data: reply })
await request
expect(resolved).toHaveBeenCalledExactlyOnceWith(reply)
receive({ source: parent, data: reply })
expect(runInContext('pending.size', context)).toBe(0)
expect(parent.postMessage).toHaveBeenCalledExactlyOnceWith(
{
type: 'orca-panel-action',
requestId: 'req-1',
action: 'workspace.readContext',
params: undefined
},
'*'
)
})
})