mirror of
https://github.com/zhw2590582/ArtPlayer.git
synced 2026-10-11 05:26:15 -08:00
build(site): [SITE-07] verify Node path origin and preserve complete notices
This commit is contained in:
1 parent
d2b2f76db8
commit
d3aa4bbfe4
24 files changed
+4050
-5
No files matched your search
@@ -3,6 +3,7 @@ import fs from 'node:fs'
|
||||
import process from 'node:process'
|
||||
import { verifyConsoleNoticeSources } from './site-vendor/console/notices.ts'
|
||||
import { verifyMonacoCoreNotices } from './site-vendor/monaco/core-origins.ts'
|
||||
import { verifyMonacoPathNotices } from './site-vendor/monaco/node-path.ts'
|
||||
import { verifyMonacoLanguageNotices } from './site-vendor/monaco/notices.ts'
|
||||
import { writeOrCheckNotices } from './site-vendor/notices.ts'
|
||||
|
||||
@@ -22,6 +23,7 @@ assert.deepEqual(manifest.groups.filter(group => group.name !== 'console').flatM
|
||||
'jsonc-parser',
|
||||
'marked (Monaco core)',
|
||||
'mutation-observer',
|
||||
'nodejs path (Monaco core)',
|
||||
'regenerator-runtime',
|
||||
'style-loader',
|
||||
'svelte',
|
||||
@@ -89,6 +91,7 @@ for (const name of ['LICENSE', 'MIT-LICENSE', 'ATTRIBUTION.md'])
|
||||
assert(vconsoleNotices?.includes(`docs/licenses/vconsole/${name}`), `Missing vConsole notice: ${name}`)
|
||||
verifyConsoleNoticeSources(process.cwd(), manifest)
|
||||
verifyMonacoCoreNotices(process.cwd(), manifest)
|
||||
verifyMonacoPathNotices(process.cwd(), manifest)
|
||||
verifyMonacoLanguageNotices(process.cwd(), manifest)
|
||||
const count = writeOrCheckNotices(process.cwd(), manifest, process.argv.includes('--check'))
|
||||
console.log(`Verified site notices: ${count} outputs; Monaco/vConsole/console inventories, embedded and other provenance gates remain open.`)
|
||||
@@ -1020,6 +1020,11 @@
|
||||
"source": "refactor/baselines/site-vendor/monaco-core-origins/ATTRIBUTION.md",
|
||||
"target": "docs/licenses/monaco-editor/core-origins/ATTRIBUTION.md",
|
||||
"sha256": "3a0ab7f1036d6b1397bf94ff2700375b97db2db3bd576d195dc6d8a88e1a758e"
|
||||
},
|
||||
{
|
||||
"source": "refactor/baselines/site-vendor/monaco-node-path/ATTRIBUTION.md.txt",
|
||||
"target": "docs/licenses/monaco-editor/core-path/ATTRIBUTION.md",
|
||||
"sha256": "40583c701c0bcbd8e10935652a0a8b02e2073b0ef040fb7be7b939c437d8b8dc"
|
||||
}
|
||||
],
|
||||
"review": "The complete upstream Monaco LICENSE/ThirdPartyNotices are retained. The unmodified bundled Codicons font exactly matches @vscode/codicons 0.0.26; its historical README, CC BY 4.0 content license, MIT code license and added attribution are distributed below. Other site assets remain subject to their separate provenance reviews.",
|
||||
@@ -1199,6 +1204,19 @@
|
||||
"docs/licenses/monaco-editor/core-origins/marked-vscode-license.txt",
|
||||
"docs/licenses/monaco-editor/core-origins/ATTRIBUTION.md"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "nodejs path (Monaco core)",
|
||||
"version": "14.16.0",
|
||||
"tarball": "https://github.com/nodejs/node/blob/bd60e93357a118204ea238d94e7a9e4209d93062/lib/path.js",
|
||||
"assets": [
|
||||
"docs/assets/js/vs/editor/editor.main.js",
|
||||
"docs/assets/js/vs/base/worker/workerMain.js"
|
||||
],
|
||||
"notices": [
|
||||
"docs/licenses/monaco-editor/ThirdPartyNotices.txt",
|
||||
"docs/licenses/monaco-editor/core-path/ATTRIBUTION.md"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@@ -325,3 +325,48 @@ Browser checks cover light/dark theme colors, layout and resize, find-widget bou
|
||||
successful CSS/font requests, loaded codicon glyphs and model disposal in all three
|
||||
engines. The pinned light theme is intentionally #fffffe. Full original core TS
|
||||
compilation and further embedded-origin review remain separate open work.
|
||||
|
||||
## Node path port and existing terms
|
||||
|
||||
`node-path.ts` binds the Node path attribution to both editor.main and workerMain.
|
||||
The original site ThirdPartyNotices already contains the full Joyent/Node license
|
||||
text, identical to Node v14.16.0 and VS Code's retained source comment. Its older
|
||||
commit link is kept intact; a new core-path/ATTRIBUTION.md identifies the actual
|
||||
fixed Node source and VS Code port. The site now delivers 86 notice files plus
|
||||
its index. The ordinary notice build rejects a missing worker binding, original
|
||||
terms, source explanation, or mismatched ported license/version.
|
||||
|
||||
`reproduce-node-path.ts` checks three archives and three fixed Git files. Six
|
||||
explicit unused top-level exports are removed from the VS Code source; the complete
|
||||
result equals both archived source-map entries. Their source keys contain different
|
||||
`out-editor/.../file:/...` prefixes, so the record uses the actual keys, not a guessed
|
||||
file URI. Historical TypeScript 4.5.0-dev.20211021 from VS Code's lock compiles the
|
||||
full path module into both development bundles with exact unique spans. It stays
|
||||
in a separate ignored compiler directory from Monaco's TypeScript 4.4.4 tools.
|
||||
The corresponding shipped minified assets are checked against their fixed archives;
|
||||
the complete core minifier was verified separately by reproduce-core-build.ts.
|
||||
|
||||
This is a modified browser port, not an unmodified Node runtime. Besides types,
|
||||
parameter names and brace style, review identified a Windows join string guard,
|
||||
shared basename loop variables, local validation/Error handling, the process
|
||||
adapter, explicit exports and omission of Node's deprecated _makeLong alias.
|
||||
The new source note records these existing adaptations without changing behavior.
|
||||
|
||||
Thirty deterministic valid calls are evaluated by the frozen Node v14.16.0 module
|
||||
and frozen as fixtures. The reference harness supplies character constants and
|
||||
string validation, rejects extra imports and cwd use, and does not emulate Node's
|
||||
error messages or per-drive environment. Browser tests execute the actual Monaco
|
||||
POSIX/Windows functions, compare those results, check platform alias selection,
|
||||
and retain the existing Error/ERR_INVALID_ARG_TYPE behavior.
|
||||
|
||||
```sh
|
||||
yarn verify:monaco-node-path --fetch
|
||||
yarn verify:monaco-node-path
|
||||
yarn build:site-notices
|
||||
yarn check:site-notices
|
||||
yarn test:browser test/browser/editor-path.spec.js test/browser/site-vendor.spec.js --workers=1
|
||||
```
|
||||
|
||||
Full original core TypeScript compilation, WinJS/Unicode/other embedded origins
|
||||
and the overall SITE-07 acceptance remain separate. A path-module proof is not
|
||||
an exhaustive claim about every Node API or the rest of Monaco.
|
||||
@@ -0,0 +1,93 @@
|
||||
import type { VendorManifest } from '../notices.ts'
|
||||
import type { Archive, Member, Remote } from './archives.ts'
|
||||
import assert from 'node:assert/strict'
|
||||
import fs from 'node:fs'
|
||||
import path from 'node:path'
|
||||
import vm from 'node:vm'
|
||||
|
||||
export interface PathProvenance {
|
||||
archives: Archive[]
|
||||
remotes: Remote[]
|
||||
nodeSource: string
|
||||
vscodeSource: string
|
||||
lockSource: string
|
||||
maps: (Member & { source: string })[]
|
||||
outputs: { development: Member, signature: string, offset: number, target: { path: string, sha256: string }, editor: Member }[]
|
||||
component: { name: string, version: string, tarball: string, assets: string[], notices: string[] }
|
||||
attribution: { source: string, target: string, sha256: string }
|
||||
legacyNotice: { source: string, target: string, sha256: string }
|
||||
fixtures: { path: string, sha256: string }
|
||||
}
|
||||
|
||||
export interface PathCase { namespace: 'win32' | 'posix', method: string, args: unknown[], expected: unknown }
|
||||
|
||||
// Evaluate the frozen Node module for valid deterministic path calls only. This
|
||||
// harness does not emulate Node's error messages, host cwd or drive environment.
|
||||
export function nodePathResults(source: string, cases: Omit<PathCase, 'expected'>[]): unknown[] {
|
||||
const constants = { CHAR_UPPERCASE_A: 65, CHAR_LOWERCASE_A: 97, CHAR_UPPERCASE_Z: 90, CHAR_LOWERCASE_Z: 122, CHAR_DOT: 46, CHAR_FORWARD_SLASH: 47, CHAR_BACKWARD_SLASH: 92, CHAR_COLON: 58, CHAR_QUESTION_MARK: 63 }
|
||||
const module = { exports: {} as Record<string, Record<string, (...args: unknown[]) => unknown>> }
|
||||
vm.runInNewContext(source, {
|
||||
module,
|
||||
process: { platform: 'linux', env: {}, cwd: () => { throw new Error('Non-deterministic path cwd') } },
|
||||
require: (name: string) => {
|
||||
if (name === 'internal/constants')
|
||||
return constants
|
||||
if (name === 'internal/validators')
|
||||
return { validateString: (value: unknown) => assert.equal(typeof value, 'string', 'Valid path fixture required') }
|
||||
assert.equal(name, 'internal/errors', 'Unexpected Node path import')
|
||||
return { codes: { ERR_INVALID_ARG_TYPE: Error } }
|
||||
},
|
||||
}, { timeout: 1000 })
|
||||
return cases.map((entry) => {
|
||||
assert(['posix', 'win32'].includes(entry.namespace))
|
||||
assert(['normalize', 'basename', 'dirname', 'extname', 'join', 'relative', 'resolve', 'parse', 'format', 'isAbsolute', 'toNamespacedPath'].includes(entry.method), 'Unexpected path fixture method')
|
||||
return JSON.parse(JSON.stringify(module.exports[entry.namespace]![entry.method]!(...entry.args)))
|
||||
})
|
||||
}
|
||||
|
||||
export function readPathProvenance(root: string): PathProvenance {
|
||||
return JSON.parse(fs.readFileSync(path.join(root, 'refactor/baselines/monaco-node-path-provenance.json'), 'utf8'))
|
||||
}
|
||||
|
||||
export function preparePathSource(source: string): string {
|
||||
for (const name of ['isAbsolute', 'join', 'format', 'parse', 'toNamespacedPath', 'delimiter']) {
|
||||
const line = `export const ${name} = (process.platform === 'win32' ? win32.${name} : posix.${name});\n`
|
||||
assert.equal(source.split(line).length, 2, `Missing or repeated unused path export: ${name}`)
|
||||
source = source.replace(line, '')
|
||||
}
|
||||
return source
|
||||
}
|
||||
|
||||
export function nodePathLicense(source: string): string {
|
||||
const boundary = source.indexOf('\n\'use strict\';')
|
||||
assert(boundary > 0, 'Missing Node source license boundary')
|
||||
const lines = source.slice(0, boundary).trimEnd().split('\n')
|
||||
assert(lines.every(line => line.startsWith('//')), 'Unexpected Node license comment')
|
||||
const license = lines.map(line => line.replace(/^\/\/ ?/, '')).join('\n')
|
||||
assert(license.startsWith('Copyright Joyent, Inc. and other Node contributors.'))
|
||||
assert(license.endsWith('USE OR OTHER DEALINGS IN THE SOFTWARE.'))
|
||||
return license
|
||||
}
|
||||
|
||||
export function verifyMonacoPathNotices(root: string, manifest: VendorManifest): void {
|
||||
const record = readPathProvenance(root)
|
||||
const group = manifest.groups.find(group => group.name === 'monaco-editor')
|
||||
assert(group, 'Missing Monaco path group')
|
||||
assert.equal(record.component.name, 'nodejs path (Monaco core)')
|
||||
assert.equal(record.component.version, '14.16.0')
|
||||
assert.deepEqual(record.component.assets, ['docs/assets/js/vs/editor/editor.main.js', 'docs/assets/js/vs/base/worker/workerMain.js'], 'Wrong Node path assets')
|
||||
assert.deepEqual(record.component.notices, [record.legacyNotice.target, record.attribution.target], 'Missing Node path terms or source explanation')
|
||||
assert.deepEqual(group.components?.filter(component => component.name === record.component.name), [record.component], 'Wrong Node path notice binding')
|
||||
for (const notice of [record.legacyNotice, record.attribution])
|
||||
assert.deepEqual(group.notices.filter(item => item.target === notice.target), [notice], 'Missing Node path notice')
|
||||
const license = nodePathLicense(fs.readFileSync(path.join(root, record.nodeSource), 'utf8'))
|
||||
const legacy = fs.readFileSync(path.join(root, record.legacyNotice.source), 'utf8').replace(/\r\n/g, '\n')
|
||||
assert(legacy.includes(license), 'Legacy notice omits actual Node path terms')
|
||||
const port = fs.readFileSync(path.join(root, record.vscodeSource), 'utf8')
|
||||
const start = port.indexOf('/**\n * Copyright Joyent, Inc. and other Node contributors.')
|
||||
assert(start >= 0, 'Missing ported Node copyright')
|
||||
const end = port.indexOf('\n */', start)
|
||||
assert(end > start, 'Missing ported Node license end')
|
||||
assert.equal(port.slice(start + 4, end).split('\n').map(line => line.replace(/^ \* ?/, '')).join('\n'), license, 'Ported Node license differs')
|
||||
assert(port.includes('https://github.com/nodejs/node/blob/v14.16.0/lib/path.js'), 'Wrong ported Node version')
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
import type { PathCase } from './node-path.ts'
|
||||
import assert from 'node:assert/strict'
|
||||
import fs from 'node:fs'
|
||||
import { createRequire } from 'node:module'
|
||||
import path from 'node:path'
|
||||
import process from 'node:process'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { ArchiveCache, hash } from './archives.ts'
|
||||
import { nodePathResults, preparePathSource, readPathProvenance, verifyMonacoPathNotices } from './node-path.ts'
|
||||
|
||||
const root = fileURLToPath(new URL('../../../', import.meta.url))
|
||||
assert(process.argv.slice(2).every(arg => arg === '--fetch'), 'Use reproduce-node-path.ts [--fetch]')
|
||||
assert.equal(process.version, `v${fs.readFileSync(path.join(root, '.node-version'), 'utf8').trim()}`, 'Use canonical Node')
|
||||
const record = readPathProvenance(root)
|
||||
const cache = new ArchiveCache(root, path.join(root, 'refactor/.cache/monaco-review'))
|
||||
await cache.verify(record.archives, record.remotes, process.argv.includes('--fetch'))
|
||||
verifyMonacoPathNotices(root, JSON.parse(fs.readFileSync(path.join(root, 'scripts/site-vendor/manifest.json'), 'utf8')))
|
||||
const compiler = record.archives.find(archive => archive.name === 'typescript')
|
||||
assert(compiler && compiler.version === '4.5.0-dev.20211021', 'Wrong path compiler')
|
||||
const lock = fs.readFileSync(path.join(root, record.lockSource), 'utf8')
|
||||
assert(lock.includes(`typescript@^4.5.0-dev.20211021:\n version "4.5.0-dev.20211021"`) && lock.includes(`integrity ${compiler.integrity}`), 'Path compiler not in upstream lock')
|
||||
const isolated = new ArchiveCache(root, path.join(cache.directory, 'core-compiler'))
|
||||
const archiveFile = `${compiler.name}-${compiler.version}.tgz`
|
||||
fs.copyFileSync(path.join(cache.directory, archiveFile), path.join(isolated.directory, archiveFile))
|
||||
isolated.extractCompiler(compiler)
|
||||
const require = createRequire(path.join(isolated.directory, 'compiler/entry.cjs'))
|
||||
const ts = require('typescript') as typeof import('typescript')
|
||||
|
||||
assert.equal(ts.version, compiler.version)
|
||||
const prepared = preparePathSource(fs.readFileSync(path.join(root, record.vscodeSource), 'utf8'))
|
||||
assert.equal(record.maps.length, 2)
|
||||
for (const member of record.maps) {
|
||||
const map: { sources: string[], sourcesContent: string[] } = JSON.parse(cache.member(member).toString('utf8'))
|
||||
assert.equal(map.sources.filter(source => source === member.source).length, 1, 'Missing or repeated mapped path source')
|
||||
assert.equal(map.sourcesContent[map.sources.indexOf(member.source)], prepared, 'Prepared path source differs')
|
||||
}
|
||||
const emitted = ts.transpileModule(prepared, { compilerOptions: { target: ts.ScriptTarget.ES2020, module: ts.ModuleKind.AMD, newLine: ts.NewLineKind.LineFeed } }).outputText
|
||||
const anonymous = 'define(["require", "exports", "vs/base/common/process"],'
|
||||
assert.equal(emitted.split(anonymous).length, 2, 'Unexpected path emission signature')
|
||||
assert.equal(record.outputs.length, 2)
|
||||
const outputs = record.outputs.map((output) => {
|
||||
assert(/^define\(__m\[\d+\/\*vs\/base\/common\/path\*\/\], __M\(\[0\/\*require\*\/,1\/\*exports\*\/,\d+\/\*vs\/base\/common\/process\*\/\]\),$/.test(output.signature), 'Unexpected path bundle signature')
|
||||
const fragment = emitted.replace(anonymous, output.signature).trimEnd()
|
||||
const development = cache.member(output.development).toString('utf8')
|
||||
assert.equal(development.indexOf(fragment), output.offset, 'Compiled path module differs')
|
||||
assert(output.offset > 0 && !development.includes(fragment, output.offset + 1), 'Missing or repeated compiled path module')
|
||||
const target = fs.readFileSync(path.join(root, output.target.path))
|
||||
assert.equal(hash(target), output.target.sha256, 'Shipped path-bearing asset changed')
|
||||
assert.deepEqual(target, cache.member(output.editor), 'Shipped path-bearing asset differs from archive')
|
||||
return { path: output.target.path, offset: output.offset, moduleBytes: new TextEncoder().encode(fragment).length, exactModule: true, sha256: hash(target) }
|
||||
})
|
||||
const fixtureBytes = fs.readFileSync(path.join(root, record.fixtures.path))
|
||||
assert.equal(hash(fixtureBytes), record.fixtures.sha256, 'Node path fixtures changed')
|
||||
const fixtures: PathCase[] = JSON.parse(fixtureBytes.toString('utf8'))
|
||||
assert.deepEqual(nodePathResults(fs.readFileSync(path.join(root, record.nodeSource), 'utf8'), fixtures), fixtures.map(fixture => fixture.expected), 'Original Node path results differ')
|
||||
console.log(JSON.stringify({ archives: record.archives.length, gitSources: record.remotes.length, maps: record.maps.length, removedUnusedExports: 6, outputs, fixtures: fixtures.length, existingLicenseTextMatches: true, compiler: ts.version, fullCoreTypeScriptBuild: false, unmodifiedNodeRuntimeClaimed: false }))
|
||||
Reference in new issue
Block a user