Replies: 2 comments 2 replies
|
我把你贴的链路对着源码核了一遍( 成立:这条链路的形状是对的
不成立:
|
|
I have a machine-measured answer to the request for a data point, and it reconciles both readings. Short version: the read-only Measured matrixSame specifier (
The no-op loader is one line and does nothing but Mechanically the hook chain runs resolution on a separate thread, so the error crosses that boundary and is re-created by Node's error (de)serialization, which installs Why the proposed one-liner would answer "not this site" on an affected machineThis is the part I would change, because it can produce a false negative on exactly the machines you want to hear from: node -e "import('...').catch(e=>{... try{e.stack='x';console.log('assignment OK')}catch(x){...}})"
So an affected reporter running your snippet would print cat > probe.mjs <<'EOF'
try { await import('@deepseek-ai/dsh-persona/locale/en.json') } catch (e) {
const d = Object.getOwnPropertyDescriptor(e, 'stack')
let assign = 'OK'; try { e.stack = 'x' } catch (x) { assign = 'THREW: ' + x.message }
console.log(process.version, e.code, JSON.stringify(d && { own: true, writable: d.writable, accessor: !!(d.get || d.set), configurable: d.configurable }), assign)
}
EOF
node probe.mjs # expect accessor / OK
node --import tsx/esm probe.mjs # expect data writable:false / THREWLine numbers
git show dsh-v0.1.7-alpha.1:packages/boot/app-boot/src/profile-resolution/resolver.ts | grep -n 'error.stack = '
# 665: if (stack !== undefined) error.stack = stack.replace(originalMessage, message)
# 688: if (stack !== undefined) error.stack = stack.replace(originalMessage, error.message)
git show dsh-v0.1.7-alpha.2:packages/boot/app-boot/src/profile-resolution/resolver.ts | grep -n 'error.stack = ' # same two lines
git show c36a83ff6b:packages/boot/app-boot/src/profile-resolution/resolver.ts | grep -n 'error.stack = ' # your commit: same two linesThose numbers hold on alpha.1, alpha.2 and on Where I partly disagree on the fixI agree with classifying by Descriptor-aware shape (the function rewriteStack(error: Error, original: string, message: string): void {
const stack = error.stack
if (stack === undefined) return
const rewritten = stack.replace(original, message)
const descriptor = Object.getOwnPropertyDescriptor(error, 'stack')
try {
if (descriptor?.get !== undefined) error.stack = rewritten
else if (descriptor !== undefined) Object.defineProperty(error, 'stack', { ...descriptor, value: rewritten })
else error.stack = rewritten
} catch {
// A stack we cannot rewrite is cosmetic. Letting this throw replaces the
// error and discards its `code`, which is how the plugin page loses the
// difference between "no locale file" and "the resolver failed".
}
}
Worth noting for anyone shipping plugins: this does not only affect built-ins. Every out-of-tree plugin without a |

I have a machine-measured answer to the request for a data point, and it reconciles both readings. Short version: the read-only
stackis real, it is not version-of-Node specific, and it is not tsx specific either — it appears whenever resolution runs through a registered module-hook chain. That is why you cannot reproduce it (no hook registered) and whypackages/contains nodefinePropertyonstack(the freeze is Node's, not the repo's).Measured matrix
Same specifier (
<pkg>/subpath-not-exported.json), same Node, one variable at a time. The descriptor is read off the realERR_PACKAGE_PATH_NOT_EXPORTED; the assignment is performed inside an ESM module (strict mode — see the trap below).