build(site): [SITE-07] verify modified forks and preserve upstream author notices

This commit is contained in:
Harvey Zhao committed 2026-09-15 07:50:12 +08:00
1 parent d2a83f8a69
commit 3136eb2402
31 files changed
+2567 -23

No files matched your search

@@ -0,0 +1,163 @@
{
"schemaVersion": 1,
"task": "SITE-07",
"archives": [
{
"id": "replicator-1.0.1",
"name": "replicator",
"version": "1.0.1",
"tarball": "https://registry.npmjs.org/replicator/-/replicator-1.0.1.tgz",
"integrity": "sha512-BwkUVdSQ08mGLa1OoP8thQ0zTUcxplGNZ1p0rsaSEL7xc4N3v5kkR/WFLjikkdjQPjp+67p24QOerWwIj2oN4g==",
"sha256": "2baede665f8f4899b7196251e39c775ee0111872f04afef08ab5e2e6ada70925",
"notices": [
{
"source": "refactor/baselines/site-vendor/console-attribution/replicator-1.0.1-LICENSE.txt",
"member": "package/LICENSE",
"sha256": "52f634086a97b3861a35afff7acf703ddbd5add8e617f6a1f540ae2f2c621284"
}
]
},
{
"id": "stylis-3.5.4",
"name": "stylis",
"version": "3.5.4",
"tarball": "https://registry.npmjs.org/stylis/-/stylis-3.5.4.tgz",
"integrity": "sha512-8/3pSmthWM7lsPBKv7NXkzn2Uc9W7NotcwGNpJaa3k7WMM1XDCA4MgT5k/8BIexd5ydZdboXtU90XH9Ec4Bv/Q==",
"sha256": "8e378e277ef50bd5282045dfac95019e66986d7d3819205a9e99c93220e3e950",
"notices": [
{
"source": "refactor/baselines/site-vendor/console-attribution/stylis-3.5.4-LICENSE.txt",
"member": "package/LICENSE.md",
"sha256": "045109dfd0547aa898408d08593e1adc41e9705519ba8a20baff89e7c6c52e91"
}
]
}
],
"compiler": {
"archive": {
"id": "typescript-4.1.2",
"name": "typescript",
"version": "4.1.2",
"tarball": "https://registry.npmjs.org/typescript/-/typescript-4.1.2.tgz",
"integrity": "sha512-thGloWsGH3SOxv1SoY7QojKi0tc+8FnOmiarEGMbd/lar7QOEd3hvlx3Fp5y6FlDUGl9L+pd4n2e+oToGMmhRQ==",
"sha256": "383b18630fc00016cb7bde65f111e79d43fccb8c025faf33d7a3a07a5abdf026"
},
"member": "package/lib/typescript.js",
"sha256": "7fb17b02f99364980c5f8540175309b09932f8fad41dcc7e9429d335535604e0",
"version": "4.1.2",
"options": {
"target": 0,
"module": 1,
"newLine": 1
}
},
"remotes": [
{
"id": "replicator-source",
"source": "refactor/baselines/site-vendor/console-attribution/replicator-source.txt",
"sha256": "2bf53776cfd80aaf6365d4419ab910ca282db649fc942ac285765748db6f875e",
"gitBlobSha": "7399074f5c003120d17d9bb48e6b0832434d64dc",
"apiUrl": "https://api.github.com/repos/samdenty/console-feed/contents/src/Transform/replicator/index.ts?ref=de41ef2662019c645a652199d9bdbbfc71419f5e",
"url": "https://github.com/samdenty/console-feed/blob/de41ef2662019c645a652199d9bdbbfc71419f5e/src/Transform/replicator/index.ts"
},
{
"id": "emotion-build",
"source": "refactor/baselines/site-vendor/console-attribution/emotion-build.txt",
"sha256": "7d9a3d176b6da384d729d45f7e36dec6cd6effb85cd19d486f4f50af5cf2925f",
"gitBlobSha": "fdd877e14000329ff556ca2f1aa7fc44c724060d",
"apiUrl": "https://api.github.com/repos/emotion-js/emotion/git/blobs/fdd877e14000329ff556ca2f1aa7fc44c724060d",
"url": "https://github.com/emotion-js/emotion/blob/6dd425bd1b8db7ab5144cca81b592639a68af2cb/packages/stylis/build.js"
},
{
"id": "emotion-stylis-source",
"source": "refactor/baselines/site-vendor/console-attribution/emotion-stylis-source.txt",
"sha256": "2d49f50cb973b395bb30ca1d03955599e6220dd347d57ae38324afe8c734506a",
"gitBlobSha": "c6b56ec79517a0dce4b84eceb15acb4730e04101",
"apiUrl": "https://api.github.com/repos/emotion-js/emotion/git/blobs/c6b56ec79517a0dce4b84eceb15acb4730e04101",
"url": "https://github.com/emotion-js/emotion/blob/6dd425bd1b8db7ab5144cca81b592639a68af2cb/packages/stylis/src/stylis.min.js"
},
{
"id": "gary-readme",
"source": "refactor/baselines/site-vendor/console-attribution/gary-readme.txt",
"sha256": "73b67c593a2a0d6395bfe90d3bad32556ed5e7ce71883062efebc643d4e4b7b4",
"gitBlobSha": "567ae1bca393a150e129cec8d60230a7b88e77c7",
"apiUrl": "https://api.github.com/repos/garycourt/murmurhash-js/contents/README.md?ref=23dc2e7008582ca3ef69d8623f02bba4c8dd05e5",
"url": "https://github.com/garycourt/murmurhash-js/blob/23dc2e7008582ca3ef69d8623f02bba4c8dd05e5/README.md"
},
{
"id": "smhasher",
"source": "refactor/baselines/site-vendor/console-attribution/smhasher.txt",
"sha256": "8cdec1fed73de41e4ee91ab78fe5ba76110582263064dcdcc0b770a25c0573f3",
"gitBlobSha": "cd1e53a9b92620d2656eae423017f81be1fb3ad1",
"apiUrl": "https://api.github.com/repos/aappleby/smhasher/contents/src/MurmurHash2.cpp?ref=61a0530f28277f2e850bfc39600ce61d02b518de",
"url": "https://github.com/aappleby/smhasher/blob/61a0530f28277f2e850bfc39600ce61d02b518de/src/MurmurHash2.cpp"
}
],
"replicator": {
"source": "replicator-source",
"target": {
"archive": "console-feed-3.2.2",
"member": "package/lib/Transform/replicator/index.js",
"sha256": "33ea546afdd46833594d7cdccbfc45dc654b8e9fa737d9ee5d940b6f164dba6b"
},
"upstream": {
"archive": "replicator-1.0.1",
"member": "package/index.js",
"sha256": "7b0f488ae3581c23d252ac5c73fd6ae35884d876bfd8e186d23bbfa5847430d7"
},
"scope": "Modified fork of the replicator 1.0.x source family; the MIT notice is taken from 1.0.1, not a claim that npm 1.0.1 is installed or identical. The fixed console-feed TS revision compiles to the exact runtime before the original inline source map."
},
"stylis": {
"source": "emotion-stylis-source",
"target": {
"archive": "%40emotion%2Fstylis-0.8.5",
"member": "package/src/stylis.min.js",
"sha256": "2d49f50cb973b395bb30ca1d03955599e6220dd347d57ae38324afe8c734506a"
},
"dependency": {
"archive": "%40emotion%2Fstylis-0.8.5",
"member": "package/package.json",
"sha256": "1da8e474cb88a0070baa42cec78a3704dea0889c4decdb38d4e7b7489c83c8b0"
},
"dependencyVersion": "3.5.4",
"recipe": "emotion-build",
"scope": "Fixed tag commit source matches npm source exactly. Its original recipe modifies Stylis and calls an unversioned online Closure compiler; this earlier compiler stage was not rerun."
},
"hash": {
"source": "smhasher",
"notice": {
"archive": "aappleby/smhasher@61a0530f28277f2e850bfc39600ce61d02b518de",
"member": "src/MurmurHash2.cpp",
"memberSha256": "8cdec1fed73de41e4ee91ab78fe5ba76110582263064dcdcc0b770a25c0573f3",
"sourceSha256": "8cdec1fed73de41e4ee91ab78fe5ba76110582263064dcdcc0b770a25c0573f3",
"start": "// MurmurHash2 was written by Austin Appleby, and is placed in the public",
"end": "// domain. The author hereby disclaims copyright to this source code.\n",
"source": "refactor/baselines/site-vendor/console-attribution/murmurhash2-public-domain.txt",
"sha256": "50e13b0a1963f0b382255d2425df245dbdfd209201621e8c157687caedbbb949"
},
"reference": {
"archive": "%40emotion%2Fhash-0.8.0",
"member": "package/dist/hash.browser.esm.js",
"sha256": "3f6d63bdf3241054ccac29fa5bad7ca228bb889a51214e22224a8fe8c6d3573d"
},
"references": [
"https://github.com/garycourt/murmurhash-js",
"61a0530f28277f2e850bfc39600ce61d02b518de"
]
},
"cache": {
"reference": {
"archive": "%40emotion%2Fcache-10.0.29",
"member": "package/dist/cache.browser.esm.js",
"sha256": "7df64362f28f43e9af8dda5dc5edc2b3c4ecb094101f7c723bc9ef03f40767f0"
},
"upstreamUrl": "https://github.com/thysultan/stylis.js/tree/master/plugins/rule-sheet",
"notice": "docs/licenses/console/stylis-rule-sheet/LICENSE"
},
"limitations": [
"No replacement or execution of archived runtime libraries.",
"Replicator is a modified fork; neither a unique npm fork base nor the entire original install lock is claimed.",
"Emotion historical online Closure service was not re-executed; its published source is pinned to the matching upstream tag commit.",
"Stack Overflow attribution and final remaining embedded-source review stay open."
]
}
@@ -0,0 +1,92 @@
{
"schemaVersion": 1,
"task": "SITE-07",
"status": "checkpoint-incomplete",
"recordedAt": "2026-09-14T23:49:08.277Z",
"baseCommit": "d2a83f8a69c7a5d9a8bf30c9b370e573034f2000",
"node": "v24.21.0",
"sourceFingerprint": {
"manifestSha256": "c0238bf1acb77ddf931c4b8702a1dc4d3ea341b525c23c78e000fff0d8109fec",
"sourceRecordSha256": "d8d5237cf261177b571b07eec17acb11f7b3905a98a2aa0675b366b8d21d7b12",
"consoleSha256": "5644af7bb35bb6d0bcfa7eeae9a21b406ac4fc1b499a6c797a6534c7d33f0678"
},
"unit": {
"passed": 24,
"failed": 0,
"log": "refactor/.cache/console-derived-tests.log"
},
"reproduction": {
"archives": 42,
"exactModules": 100,
"embeddedNotices": 2,
"mappedMembers": 17,
"transformedMembers": 7,
"derivedGitSources": 5,
"replicatorFork": true,
"emotionStylisSource": true,
"offlineLog": "refactor/.cache/console-derived-reproduce.log",
"fetchLog": "refactor/.cache/console-derived-fetch.log",
"licenseClosure": false
},
"browser": {
"report": "refactor/.cache/browser/report.json",
"sha256": "b902b3ac4e6f83a825112dda5f6ef815326c268893264c08d17bf2b44bb08cf0",
"tests": [
{
"project": "chromium",
"status": "passed",
"retry": 0,
"browser": "153.0.8010.12",
"platform": "win32",
"errors": [],
"consoleErrors": [],
"failedRequests": [
{
"url": "http://127.0.0.1:8084/test/pattern.mp4",
"resourceType": "media",
"failure": {
"errorText": "net::ERR_ABORTED"
}
}
]
},
{
"project": "firefox",
"status": "passed",
"retry": 0,
"browser": "155.0",
"platform": "win32",
"errors": [],
"consoleErrors": [],
"failedRequests": []
},
{
"project": "webkit",
"status": "passed",
"retry": 0,
"browser": "26.6",
"platform": "win32",
"errors": [],
"consoleErrors": [],
"failedRequests": []
}
],
"noticeFilesPerEngine": 60
},
"checks": [
"Strict docs-tools TypeScript",
"Scoped source/test/maintenance ESLint",
"Read-only console and site-notice generation checks"
],
"remaining": [
"Component Stack Overflow attribution and final embedded-source review",
"Other site asset provenance tasks"
],
"limits": [
"Replicator is a modified source-family fork, not an unmodified npm 1.0.1 installation.",
"Original Emotion online Closure compiler stage was not rerun; its generated source matches the immutable tag commit.",
"No claim of the unique original full dependency lockfile.",
"HTTPS integrations isolated; Windows local-page evidence does not replace physical-device or remote-publish validation.",
"No runtime or lockfile changes, pushes, deployments or publications."
]
}
@@ -30,11 +30,11 @@
"Chromium copyright and full BSD conditions in console-feed source",
"Sultan Tarimo MIT header in styled-components embedded rule-sheet source",
"All seven linkifyjs simple-html-tokenizer files exactly reproduce from its fixed Git dependency with Babel 6.26.0; Yehuda Katz license preserved.",
"All 17 react-inspector external source-map members exactly match Babel runtime 7.13.10 and regenerator-runtime 0.13.7; both licenses preserved."
"All 17 react-inspector external source-map members exactly match Babel runtime 7.13.10 and regenerator-runtime 0.13.7; both licenses preserved.",
"Modified replicator fork has fixed console-feed TS source matching the archived runtime, with Ivan Nikulin MIT attribution.",
"Emotion Stylis pinned source and 3.5.4 dependency, rule-sheet source references, and MurmurHash references retain Sultan Tarimo, Gary Court and Austin Appleby notices; historical Closure stage not rerun."
],
"pending": [
"console-feed replicator upstream attribution",
"Emotion stylis/hash and cache rule-sheet attribution",
"console-feed Component Stack Overflow attribution and any additional embedded sources"
]
}
@@ -0,0 +1,140 @@
// this whole thing is a really fragile hack
// but it works so ¯\_(ツ)_/¯
const stylisPath = require.resolve('stylis')
const { promisify } = require('util')
const j = require('jscodeshift')
const request = require('request-promise-native')
const fs = require('fs')
const prettier = require('prettier')
const recast = require('recast')
const readFile = promisify(fs.readFile)
const writeFile = promisify(fs.writeFile)
const simplifySet = src =>
j(src)
.find(j.FunctionDeclaration, { id: { name: 'set' } })
.forEach(path => {
j(path).replaceWith(
recast.parse(`function set(options) {
var prefixOpt = options.prefix
if (prefixOpt!==undefined) {
should = null
if (!prefixOpt) {
prefix = 0
} else if (typeof prefixOpt !== 'function') {
prefix = 1
} else {
prefix = 2
should = prefixOpt
}
}
return set
}`).program.body[0]
)
})
.toSource()
const removeOptions = src =>
j(src)
.find(j.SwitchStatement)
.forEach(thing => {
thing.value.cases = thing.value.cases.filter(node => {
if (!node.test) return true
switch (node.test.value) {
case 'keyframe':
case 'cascade':
case 'preserve':
case 'semicolon':
case 'compress':
case 'global': {
return false
}
default: {
return true
}
}
})
})
.toSource()
const setOptions = src =>
j(src)
.find(j.VariableDeclarator)
.forEach(path => {
switch (path.value.id.name) {
case 'escape':
case 'keyed': {
path.value.init.value = 0
return
}
case 'semicolon': {
path.value.init.value = 1
}
}
})
.toSource()
const removeUMDWrapper = src => {
let code
j(src)
.find(j.FunctionExpression, { id: { name: 'factory' } })
.forEach(path => {
code = j(path).toSource()
})
.toSource()
return "'use strict';\nwindow['stylis'] = " + code
}
async function doThing() {
const stylisSrc = (await readFile(stylisPath))
.toString()
.replace(
'cascade + quote + bracket + atrule === 0 && id !== KEYFRAME && code !== SEMICOLON',
'true === false'
)
.replace(
'comment + quote + parentheses + bracket + semicolon === 0',
'true === false'
)
.replace('switch (selector.charCodeAt(1))', 'switch (100)')
.replace('(insert === 1)', '(true === false)')
.replace('input.charCodeAt(9)*keyed', '0')
.replace('switch (cascade + level) {', 'switch (2) {')
.replace('compress*code === 0', 'true')
.replace(`typeof(output = result) !== 'string'`, '(output = result)')
// .replace("stylis['set'] = set", '')
// .replace('set(options)', '')
.replace('this !== void 0 && this.constructor === stylis', 'false')
.replace('return factory(selector)', '')
const result = removeUMDWrapper(
simplifySet(setOptions(removeOptions(stylisSrc)))
)
// await writeFile('./src/stylis.js', result)
console.log('start request')
const data = (await request('https://closure-compiler.appspot.com/compile', {
method: 'POST',
form: {
js_code: result,
compilation_level: 'ADVANCED_OPTIMIZATIONS',
output_format: 'text',
output_info: 'compiled_code'
}
})).toString()
let finalSrc = data.replace('window.stylis=', 'export default ')
await writeFile(
'./src/stylis.min.js',
prettier.format(finalSrc, {
semi: false,
singleQuote: true
})
)
console.log('done')
}
doThing()
@@ -0,0 +1,625 @@
export default function(W) {
function M(d, c, e, h, a) {
for (
var m = 0,
b = 0,
v = 0,
n = 0,
q,
g,
x = 0,
K = 0,
k,
u = (k = q = 0),
l = 0,
r = 0,
I = 0,
t = 0,
B = e.length,
J = B - 1,
y,
f = '',
p = '',
F = '',
G = '',
C;
l < B;
) {
g = e.charCodeAt(l)
l === J &&
0 !== b + n + v + m &&
(0 !== b && (g = 47 === b ? 10 : 47), (n = v = m = 0), B++, J++)
if (0 === b + n + v + m) {
if (l === J && (0 < r && (f = f.replace(N, '')), 0 < f.trim().length)) {
switch (g) {
case 32:
case 9:
case 59:
case 13:
case 10:
break
default:
f += e.charAt(l)
}
g = 59
}
switch (g) {
case 123:
f = f.trim()
q = f.charCodeAt(0)
k = 1
for (t = ++l; l < B; ) {
switch ((g = e.charCodeAt(l))) {
case 123:
k++
break
case 125:
k--
break
case 47:
switch ((g = e.charCodeAt(l + 1))) {
case 42:
case 47:
a: {
for (u = l + 1; u < J; ++u)
switch (e.charCodeAt(u)) {
case 47:
if (
42 === g &&
42 === e.charCodeAt(u - 1) &&
l + 2 !== u
) {
l = u + 1
break a
}
break
case 10:
if (47 === g) {
l = u + 1
break a
}
}
l = u
}
}
break
case 91:
g++
case 40:
g++
case 34:
case 39:
for (; l++ < J && e.charCodeAt(l) !== g; );
}
if (0 === k) break
l++
}
k = e.substring(t, l)
0 === q && (q = (f = f.replace(ca, '').trim()).charCodeAt(0))
switch (q) {
case 64:
0 < r && (f = f.replace(N, ''))
g = f.charCodeAt(1)
switch (g) {
case 100:
case 109:
case 115:
case 45:
r = c
break
default:
r = O
}
k = M(c, r, k, g, a + 1)
t = k.length
0 < A &&
((r = X(O, f, I)),
(C = H(3, k, r, c, D, z, t, g, a, h)),
(f = r.join('')),
void 0 !== C &&
0 === (t = (k = C.trim()).length) &&
((g = 0), (k = '')))
if (0 < t)
switch (g) {
case 115:
f = f.replace(da, ea)
case 100:
case 109:
case 45:
k = f + '{' + k + '}'
break
case 107:
f = f.replace(fa, '$1 $2')
k = f + '{' + k + '}'
k =
1 === w || (2 === w && L('@' + k, 3))
? '@-webkit-' + k + '@' + k
: '@' + k
break
default:
;(k = f + k), 112 === h && (k = ((p += k), ''))
}
else k = ''
break
default:
k = M(c, X(c, f, I), k, h, a + 1)
}
F += k
k = I = r = u = q = 0
f = ''
g = e.charCodeAt(++l)
break
case 125:
case 59:
f = (0 < r ? f.replace(N, '') : f).trim()
if (1 < (t = f.length))
switch (
(0 === u &&
((q = f.charCodeAt(0)), 45 === q || (96 < q && 123 > q)) &&
(t = (f = f.replace(' ', ':')).length),
0 < A &&
void 0 !== (C = H(1, f, c, d, D, z, p.length, h, a, h)) &&
0 === (t = (f = C.trim()).length) &&
(f = '\x00\x00'),
(q = f.charCodeAt(0)),
(g = f.charCodeAt(1)),
q)
) {
case 0:
break
case 64:
if (105 === g || 99 === g) {
G += f + e.charAt(l)
break
}
default:
58 !== f.charCodeAt(t - 1) &&
(p += P(f, q, g, f.charCodeAt(2)))
}
I = r = u = q = 0
f = ''
g = e.charCodeAt(++l)
}
}
switch (g) {
case 13:
case 10:
47 === b
? (b = 0)
: 0 === 1 + q &&
107 !== h &&
0 < f.length &&
((r = 1), (f += '\x00'))
0 < A * Y && H(0, f, c, d, D, z, p.length, h, a, h)
z = 1
D++
break
case 59:
case 125:
if (0 === b + n + v + m) {
z++
break
}
default:
z++
y = e.charAt(l)
switch (g) {
case 9:
case 32:
if (0 === n + m + b)
switch (x) {
case 44:
case 58:
case 9:
case 32:
y = ''
break
default:
32 !== g && (y = ' ')
}
break
case 0:
y = '\\0'
break
case 12:
y = '\\f'
break
case 11:
y = '\\v'
break
case 38:
0 === n + b + m && ((r = I = 1), (y = '\f' + y))
break
case 108:
if (0 === n + b + m + E && 0 < u)
switch (l - u) {
case 2:
112 === x && 58 === e.charCodeAt(l - 3) && (E = x)
case 8:
111 === K && (E = K)
}
break
case 58:
0 === n + b + m && (u = l)
break
case 44:
0 === b + v + n + m && ((r = 1), (y += '\r'))
break
case 34:
case 39:
0 === b && (n = n === g ? 0 : 0 === n ? g : n)
break
case 91:
0 === n + b + v && m++
break
case 93:
0 === n + b + v && m--
break
case 41:
0 === n + b + m && v--
break
case 40:
if (0 === n + b + m) {
if (0 === q)
switch (2 * x + 3 * K) {
case 533:
break
default:
q = 1
}
v++
}
break
case 64:
0 === b + v + n + m + u + k && (k = 1)
break
case 42:
case 47:
if (!(0 < n + m + v))
switch (b) {
case 0:
switch (2 * g + 3 * e.charCodeAt(l + 1)) {
case 235:
b = 47
break
case 220:
;(t = l), (b = 42)
}
break
case 42:
47 === g &&
42 === x &&
t + 2 !== l &&
(33 === e.charCodeAt(t + 2) &&
(p += e.substring(t, l + 1)),
(y = ''),
(b = 0))
}
}
0 === b && (f += y)
}
K = x
x = g
l++
}
t = p.length
if (0 < t) {
r = c
if (
0 < A &&
((C = H(2, p, r, d, D, z, t, h, a, h)),
void 0 !== C && 0 === (p = C).length)
)
return G + p + F
p = r.join(',') + '{' + p + '}'
if (0 !== w * E) {
2 !== w || L(p, 2) || (E = 0)
switch (E) {
case 111:
p = p.replace(ha, ':-moz-$1') + p
break
case 112:
p =
p.replace(Q, '::-webkit-input-$1') +
p.replace(Q, '::-moz-$1') +
p.replace(Q, ':-ms-input-$1') +
p
}
E = 0
}
}
return G + p + F
}
function X(d, c, e) {
var h = c.trim().split(ia)
c = h
var a = h.length,
m = d.length
switch (m) {
case 0:
case 1:
var b = 0
for (d = 0 === m ? '' : d[0] + ' '; b < a; ++b)
c[b] = Z(d, c[b], e, m).trim()
break
default:
var v = (b = 0)
for (c = []; b < a; ++b)
for (var n = 0; n < m; ++n) c[v++] = Z(d[n] + ' ', h[b], e, m).trim()
}
return c
}
function Z(d, c, e) {
var h = c.charCodeAt(0)
33 > h && (h = (c = c.trim()).charCodeAt(0))
switch (h) {
case 38:
return c.replace(F, '$1' + d.trim())
case 58:
return d.trim() + c.replace(F, '$1' + d.trim())
default:
if (0 < 1 * e && 0 < c.indexOf('\f'))
return c.replace(F, (58 === d.charCodeAt(0) ? '' : '$1') + d.trim())
}
return d + c
}
function P(d, c, e, h) {
var a = d + ';',
m = 2 * c + 3 * e + 4 * h
if (944 === m) {
d = a.indexOf(':', 9) + 1
var b = a.substring(d, a.length - 1).trim()
b = a.substring(0, d).trim() + b + ';'
return 1 === w || (2 === w && L(b, 1)) ? '-webkit-' + b + b : b
}
if (0 === w || (2 === w && !L(a, 1))) return a
switch (m) {
case 1015:
return 97 === a.charCodeAt(10) ? '-webkit-' + a + a : a
case 951:
return 116 === a.charCodeAt(3) ? '-webkit-' + a + a : a
case 963:
return 110 === a.charCodeAt(5) ? '-webkit-' + a + a : a
case 1009:
if (100 !== a.charCodeAt(4)) break
case 969:
case 942:
return '-webkit-' + a + a
case 978:
return '-webkit-' + a + '-moz-' + a + a
case 1019:
case 983:
return '-webkit-' + a + '-moz-' + a + '-ms-' + a + a
case 883:
if (45 === a.charCodeAt(8)) return '-webkit-' + a + a
if (0 < a.indexOf('image-set(', 11))
return a.replace(ja, '$1-webkit-$2') + a
break
case 932:
if (45 === a.charCodeAt(4))
switch (a.charCodeAt(5)) {
case 103:
return (
'-webkit-box-' +
a.replace('-grow', '') +
'-webkit-' +
a +
'-ms-' +
a.replace('grow', 'positive') +
a
)
case 115:
return (
'-webkit-' + a + '-ms-' + a.replace('shrink', 'negative') + a
)
case 98:
return (
'-webkit-' +
a +
'-ms-' +
a.replace('basis', 'preferred-size') +
a
)
}
return '-webkit-' + a + '-ms-' + a + a
case 964:
return '-webkit-' + a + '-ms-flex-' + a + a
case 1023:
if (99 !== a.charCodeAt(8)) break
b = a
.substring(a.indexOf(':', 15))
.replace('flex-', '')
.replace('space-between', 'justify')
return '-webkit-box-pack' + b + '-webkit-' + a + '-ms-flex-pack' + b + a
case 1005:
return ka.test(a)
? a.replace(aa, ':-webkit-') + a.replace(aa, ':-moz-') + a
: a
case 1e3:
b = a.substring(13).trim()
c = b.indexOf('-') + 1
switch (b.charCodeAt(0) + b.charCodeAt(c)) {
case 226:
b = a.replace(G, 'tb')
break
case 232:
b = a.replace(G, 'tb-rl')
break
case 220:
b = a.replace(G, 'lr')
break
default:
return a
}
return '-webkit-' + a + '-ms-' + b + a
case 1017:
if (-1 === a.indexOf('sticky', 9)) break
case 975:
c = (a = d).length - 10
b = (33 === a.charCodeAt(c) ? a.substring(0, c) : a)
.substring(d.indexOf(':', 7) + 1)
.trim()
switch ((m = b.charCodeAt(0) + (b.charCodeAt(7) | 0))) {
case 203:
if (111 > b.charCodeAt(8)) break
case 115:
a = a.replace(b, '-webkit-' + b) + ';' + a
break
case 207:
case 102:
a =
a.replace(b, '-webkit-' + (102 < m ? 'inline-' : '') + 'box') +
';' +
a.replace(b, '-webkit-' + b) +
';' +
a.replace(b, '-ms-' + b + 'box') +
';' +
a
}
return a + ';'
case 938:
if (45 === a.charCodeAt(5))
switch (a.charCodeAt(6)) {
case 105:
return (
(b = a.replace('-items', '')),
'-webkit-' + a + '-webkit-box-' + b + '-ms-flex-' + b + a
)
case 115:
return '-webkit-' + a + '-ms-flex-item-' + a.replace(ba, '') + a
default:
return (
'-webkit-' +
a +
'-ms-flex-line-pack' +
a.replace('align-content', '').replace(ba, '') +
a
)
}
break
case 973:
case 989:
if (45 !== a.charCodeAt(3) || 122 === a.charCodeAt(4)) break
case 931:
case 953:
if (!0 === la.test(d))
return 115 === (b = d.substring(d.indexOf(':') + 1)).charCodeAt(0)
? P(d.replace('stretch', 'fill-available'), c, e, h).replace(
':fill-available',
':stretch'
)
: a.replace(b, '-webkit-' + b) +
a.replace(b, '-moz-' + b.replace('fill-', '')) +
a
break
case 962:
if (
((a =
'-webkit-' + a + (102 === a.charCodeAt(5) ? '-ms-' + a : '') + a),
211 === e + h &&
105 === a.charCodeAt(13) &&
0 < a.indexOf('transform', 10))
)
return (
a.substring(0, a.indexOf(';', 27) + 1).replace(ma, '$1-webkit-$2') +
a
)
}
return a
}
function L(d, c) {
var e = d.indexOf(1 === c ? ':' : '{'),
h = d.substring(0, 3 !== c ? e : 10)
e = d.substring(e + 1, d.length - 1)
return R(2 !== c ? h : h.replace(na, '$1'), e, c)
}
function ea(d, c) {
var e = P(c, c.charCodeAt(0), c.charCodeAt(1), c.charCodeAt(2))
return e !== c + ';'
? e.replace(oa, ' or ($1)').substring(4)
: '(' + c + ')'
}
function H(d, c, e, h, a, m, b, v, n, q) {
for (var g = 0, x = c, w; g < A; ++g)
switch ((w = S[g].call(B, d, x, e, h, a, m, b, v, n, q))) {
case void 0:
case !1:
case !0:
case null:
break
default:
x = w
}
if (x !== c) return x
}
function T(d) {
switch (d) {
case void 0:
case null:
A = S.length = 0
break
default:
if ('function' === typeof d) S[A++] = d
else if ('object' === typeof d)
for (var c = 0, e = d.length; c < e; ++c) T(d[c])
else Y = !!d | 0
}
return T
}
function U(d) {
d = d.prefix
void 0 !== d &&
((R = null),
d ? ('function' !== typeof d ? (w = 1) : ((w = 2), (R = d))) : (w = 0))
return U
}
function B(d, c) {
var e = d
33 > e.charCodeAt(0) && (e = e.trim())
V = e
e = [V]
if (0 < A) {
var h = H(-1, c, e, e, D, z, 0, 0, 0, 0)
void 0 !== h && 'string' === typeof h && (c = h)
}
var a = M(O, e, c, 0, 0)
0 < A &&
((h = H(-2, a, e, e, D, z, a.length, 0, 0, 0)), void 0 !== h && (a = h))
V = ''
E = 0
z = D = 1
return a
}
var ca = /^\0+/g,
N = /[\0\r\f]/g,
aa = /: */g,
ka = /zoo|gra/,
ma = /([,: ])(transform)/g,
ia = /,\r+?/g,
F = /([\t\r\n ])*\f?&/g,
fa = /@(k\w+)\s*(\S*)\s*/,
Q = /::(place)/g,
ha = /:(read-only)/g,
G = /[svh]\w+-[tblr]{2}/,
da = /\(\s*(.*)\s*\)/g,
oa = /([\s\S]*?);/g,
ba = /-self|flex-/g,
na = /[^]*?(:[rp][el]a[\w-]+)[^]*/,
la = /stretch|:\s*\w+\-(?:conte|avail)/,
ja = /([^-])(image-set\()/,
z = 1,
D = 1,
E = 0,
w = 1,
O = [],
S = [],
A = 0,
R = null,
Y = 0,
V = ''
B.use = T
B.set = U
void 0 !== W && U(W)
return B
}
@@ -0,0 +1,20 @@
# MurmurHash.js
An optimized JavaScript implementation of the MurmurHash algorithms.
These algorithms take a JavaScript string (and a seed), and quickly create a non-cryptographic 32-bit hash from it. And by quick I mean sub-millisecond performance.
More information about these algorithms can be found at:
* [MurmurHash Homepage](http://sites.google.com/site/murmurhash/)
* [Wikipedia Entry on MurmurHash](http://en.wikipedia.org/wiki/MurmurHash)
## License (MIT)
Copyright (c) 2011 Gary Court
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,2 @@
// MurmurHash2 was written by Austin Appleby, and is placed in the public
// domain. The author hereby disclaims copyright to this source code.
@@ -0,0 +1,22 @@
The MIT License (MIT)
Copyright (c) 2016 Ivan Nikulin (ifaaan@gmail.com, https://github.com/inikulin)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
@@ -0,0 +1,588 @@
// Const
const TRANSFORMED_TYPE_KEY = '@t'
const CIRCULAR_REF_KEY = '@r'
const KEY_REQUIRE_ESCAPING_RE = /^#*@(t|r)$/
const GLOBAL = (function getGlobal() {
// NOTE: see http://www.ecma-international.org/ecma-262/6.0/index.html#sec-performeval step 10
const savedEval = eval
return savedEval('this')
})()
const ARRAY_BUFFER_SUPPORTED = typeof ArrayBuffer === 'function'
const MAP_SUPPORTED = typeof Map === 'function'
const SET_SUPPORTED = typeof Set === 'function'
const TYPED_ARRAY_CTORS = [
'Int8Array',
'Uint8Array',
'Uint8ClampedArray',
'Int16Array',
'Uint16Array',
'Int32Array',
'Uint32Array',
'Float32Array',
'Float64Array',
]
// Saved proto functions
const arrSlice = Array.prototype.slice
// Default serializer
const JSONSerializer = {
serialize(val: any) {
return JSON.stringify(val)
},
deserialize(val: any) {
return JSON.parse(val)
},
}
// EncodingTransformer
class EncodingTransformer {
references: any
transforms: any
circularCandidates: any
circularCandidatesDescrs: any
circularRefCount: any
constructor(val: any, transforms: any) {
this.references = val
this.transforms = transforms
this.circularCandidates = []
this.circularCandidatesDescrs = []
this.circularRefCount = 0
}
static _createRefMark(idx: any) {
const obj = Object.create(null)
obj[CIRCULAR_REF_KEY] = idx
return obj
}
_createCircularCandidate(val: any, parent: any, key: any) {
this.circularCandidates.push(val)
this.circularCandidatesDescrs.push({ parent, key, refIdx: -1 })
}
_applyTransform(val: any, parent: any, key: any, transform: any) {
const result = Object.create(null)
const serializableVal = transform.toSerializable(val)
if (typeof serializableVal === 'object')
this._createCircularCandidate(val, parent, key)
result[TRANSFORMED_TYPE_KEY] = transform.type
result.data = this._handleValue(() => serializableVal, parent, key)
return result
}
_handleArray(arr: any): any {
const result = [] as any
for (let i = 0; i < arr.length; i++)
result[i] = this._handleValue(() => arr[i], result, i)
return result
}
_handlePlainObject(obj: any) {
const result = Object.create(null)
for (const key in obj) {
if (Reflect.has(obj, key)) {
const resultKey = KEY_REQUIRE_ESCAPING_RE.test(key) ? `#${key}` : key
result[resultKey] = this._handleValue(() => obj[key], result, resultKey)
}
}
const name = obj?.__proto__?.constructor?.name
if (name && name !== 'Object') {
result.constructor = { name }
}
return result
}
_handleObject(obj: any, parent: any, key: any) {
this._createCircularCandidate(obj, parent, key)
return Array.isArray(obj)
? this._handleArray(obj)
: this._handlePlainObject(obj)
}
_ensureCircularReference(obj: any) {
const circularCandidateIdx = this.circularCandidates.indexOf(obj)
if (circularCandidateIdx > -1) {
const descr = this.circularCandidatesDescrs[circularCandidateIdx]
if (descr.refIdx === -1)
descr.refIdx = descr.parent ? ++this.circularRefCount : 0
return EncodingTransformer._createRefMark(descr.refIdx)
}
return null
}
_handleValue(getVal: () => any, parent: any, key: any) {
try {
const val = getVal()
const type = typeof val
const isObject = type === 'object' && val !== null
if (isObject) {
const refMark = this._ensureCircularReference(val)
if (refMark) return refMark
}
for (const transform of this.transforms) {
if (transform.shouldTransform(type, val))
return this._applyTransform(val, parent, key, transform)
}
if (isObject) return this._handleObject(val, parent, key)
return val
} catch (e) {
try {
return this._handleValue(
() => (e instanceof Error ? e : new Error(e)),
parent,
key
)
} catch {
return null
}
}
}
transform() {
const references = [this._handleValue(() => this.references, null, null)]
for (const descr of this.circularCandidatesDescrs) {
if (descr.refIdx > 0) {
references[descr.refIdx] = descr.parent[descr.key]
descr.parent[descr.key] = EncodingTransformer._createRefMark(
descr.refIdx
)
}
}
return references
}
}
// DecodingTransform
class DecodingTransformer {
references: any
transformMap: any
activeTransformsStack = [] as any
visitedRefs = Object.create(null)
constructor(references: any, transformsMap: any) {
this.references = references
this.transformMap = transformsMap
}
_handlePlainObject(obj: any) {
const unescaped = Object.create(null)
if ('constructor' in obj) {
if (!obj.constructor || typeof obj.constructor.name !== 'string') {
obj.constructor = {
name: 'Object',
}
}
}
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
this._handleValue(obj[key], obj, key)
if (KEY_REQUIRE_ESCAPING_RE.test(key)) {
// NOTE: use intermediate object to avoid unescaped and escaped keys interference
// E.g. unescaped "##@t" will be "#@t" which can overwrite escaped "#@t".
unescaped[key.substring(1)] = obj[key]
delete obj[key]
}
}
}
for (const unsecapedKey in unescaped)
obj[unsecapedKey] = unescaped[unsecapedKey]
}
_handleTransformedObject(obj: any, parent: any, key: any) {
const transformType = obj[TRANSFORMED_TYPE_KEY]
const transform = this.transformMap[transformType]
if (!transform)
throw new Error(`Can't find transform for "${transformType}" type.`)
this.activeTransformsStack.push(obj)
this._handleValue(obj.data, obj, 'data')
this.activeTransformsStack.pop()
parent[key] = transform.fromSerializable(obj.data)
}
_handleCircularSelfRefDuringTransform(refIdx: any, parent: any, key: any) {
// NOTE: we've hit a hard case: object reference itself during transformation.
// We can't dereference it since we don't have resulting object yet. And we'll
// not be able to restore reference lately because we will need to traverse
// transformed object again and reference might be unreachable or new object contain
// new circular references. As a workaround we create getter, so once transformation
// complete, dereferenced property will point to correct transformed object.
const references = this.references
Object.defineProperty(parent, key, {
// @ts-ignore
val: void 0,
configurable: true,
enumerable: true,
get() {
if (this.val === void 0) this.val = references[refIdx]
return (<any>this).val
},
set(value) {
this.val = value
},
})
}
_handleCircularRef(refIdx: any, parent: any, key: any) {
if (this.activeTransformsStack.includes(this.references[refIdx]))
this._handleCircularSelfRefDuringTransform(refIdx, parent, key)
else {
if (!this.visitedRefs[refIdx]) {
this.visitedRefs[refIdx] = true
this._handleValue(this.references[refIdx], this.references, refIdx)
}
parent[key] = this.references[refIdx]
}
}
_handleValue(val: any, parent: any, key: any) {
if (typeof val !== 'object' || val === null) return
const refIdx = val[CIRCULAR_REF_KEY]
if (refIdx !== void 0) this._handleCircularRef(refIdx, parent, key)
else if (val[TRANSFORMED_TYPE_KEY])
this._handleTransformedObject(val, parent, key)
else if (Array.isArray(val)) {
for (let i = 0; i < val.length; i++) this._handleValue(val[i], val, i)
} else this._handlePlainObject(val)
}
transform() {
this.visitedRefs[0] = true
this._handleValue(this.references[0], this.references, 0)
return this.references[0]
}
}
// Transforms
const builtInTransforms = [
{
type: '[[NaN]]',
shouldTransform(type: any, val: any) {
return type === 'number' && isNaN(val)
},
toSerializable() {
return ''
},
fromSerializable() {
return NaN
},
},
{
type: '[[undefined]]',
shouldTransform(type: any) {
return type === 'undefined'
},
toSerializable() {
return ''
},
fromSerializable() {
return void 0
},
},
{
type: '[[Date]]',
shouldTransform(type: any, val: any) {
return val instanceof Date
},
toSerializable(date: any) {
return date.getTime()
},
fromSerializable(val: any) {
const date = new Date()
date.setTime(val)
return date
},
},
{
type: '[[RegExp]]',
shouldTransform(type: any, val: any) {
return val instanceof RegExp
},
toSerializable(re: any) {
const result = {
src: re.source,
flags: '',
}
if (re.global) result.flags += 'g'
if (re.ignoreCase) result.flags += 'i'
if (re.multiline) result.flags += 'm'
return result
},
fromSerializable(val: any) {
return new RegExp(val.src, val.flags)
},
},
{
type: '[[Error]]',
shouldTransform(type: any, val: any) {
return val instanceof Error
},
toSerializable(err: any) {
if (!err.stack) {
;(Error as any).captureStackTrace?.(err)
}
return {
name: err.name,
message: err.message,
stack: err.stack,
}
},
fromSerializable(val: any) {
const Ctor = GLOBAL[val.name] || Error
const err = new Ctor(val.message)
err.stack = val.stack
return err
},
},
{
type: '[[ArrayBuffer]]',
shouldTransform(type: any, val: any) {
return ARRAY_BUFFER_SUPPORTED && val instanceof ArrayBuffer
},
toSerializable(buffer: any) {
const view = new Int8Array(buffer)
return arrSlice.call(view)
},
fromSerializable(val: any) {
if (ARRAY_BUFFER_SUPPORTED) {
const buffer = new ArrayBuffer(val.length)
const view = new Int8Array(buffer)
view.set(val)
return buffer
}
return val
},
},
{
type: '[[TypedArray]]',
shouldTransform(type: any, val: any) {
for (const ctorName of TYPED_ARRAY_CTORS) {
if (
typeof GLOBAL[ctorName] === 'function' &&
val instanceof GLOBAL[ctorName]
)
return true
}
return false
},
toSerializable(arr: any) {
return {
ctorName: arr.constructor.name,
arr: arrSlice.call(arr),
}
},
fromSerializable(val: any) {
return typeof GLOBAL[val.ctorName] === 'function'
? new GLOBAL[val.ctorName](val.arr)
: val.arr
},
},
{
type: '[[Map]]',
shouldTransform(type: any, val: any) {
return MAP_SUPPORTED && val instanceof Map
},
toSerializable(map: any) {
const flattenedKVArr: any = []
map.forEach((val: any, key: any) => {
flattenedKVArr.push(key)
flattenedKVArr.push(val)
})
return flattenedKVArr
},
fromSerializable(val: any) {
if (MAP_SUPPORTED) {
// NOTE: new Map(iterable) is not supported by all browsers
const map = new Map()
for (var i = 0; i < val.length; i += 2) map.set(val[i], val[i + 1])
return map
}
const kvArr = []
// @ts-ignore
for (let j = 0; j < val.length; j += 2) kvArr.push([val[i], val[i + 1]])
return kvArr
},
},
{
type: '[[Set]]',
shouldTransform(type: any, val: any) {
return SET_SUPPORTED && val instanceof Set
},
toSerializable(set: any) {
const arr: any = []
set.forEach((val: any) => {
arr.push(val)
})
return arr
},
fromSerializable(val: any) {
if (SET_SUPPORTED) {
// NOTE: new Set(iterable) is not supported by all browsers
const set = new Set()
for (let i = 0; i < val.length; i++) set.add(val[i])
return set
}
return val
},
},
]
// Replicator
class Replicator {
transforms = [] as any
transformsMap = Object.create(null)
serializer: any
constructor(serializer?: any) {
this.serializer = serializer || JSONSerializer
this.addTransforms(builtInTransforms)
}
addTransforms(transforms: any) {
transforms = Array.isArray(transforms) ? transforms : [transforms]
for (const transform of transforms) {
if (this.transformsMap[transform.type])
throw new Error(
`Transform with type "${transform.type}" was already added.`
)
this.transforms.push(transform)
this.transformsMap[transform.type] = transform
}
return this
}
removeTransforms(transforms: any) {
transforms = Array.isArray(transforms) ? transforms : [transforms]
for (const transform of transforms) {
const idx = this.transforms.indexOf(transform)
if (idx > -1) this.transforms.splice(idx, 1)
delete this.transformsMap[transform.type]
}
return this
}
encode(val: any) {
const transformer = new EncodingTransformer(val, this.transforms)
const references = transformer.transform()
return this.serializer.serialize(references)
}
decode(val: any) {
const references = this.serializer.deserialize(val)
const transformer = new DecodingTransformer(references, this.transformsMap)
return transformer.transform()
}
}
export default Replicator
@@ -0,0 +1,523 @@
//-----------------------------------------------------------------------------
// MurmurHash2 was written by Austin Appleby, and is placed in the public
// domain. The author hereby disclaims copyright to this source code.
// Note - This code makes a few assumptions about how your machine behaves -
// 1. We can read a 4-byte value from any address without crashing
// 2. sizeof(int) == 4
// And it has a few limitations -
// 1. It will not work incrementally.
// 2. It will not produce the same results on little-endian and big-endian
// machines.
#include "MurmurHash2.h"
//-----------------------------------------------------------------------------
// Platform-specific functions and macros
// Microsoft Visual Studio
#if defined(_MSC_VER)
#define BIG_CONSTANT(x) (x)
// Other compilers
#else // defined(_MSC_VER)
#define BIG_CONSTANT(x) (x##LLU)
#endif // !defined(_MSC_VER)
//-----------------------------------------------------------------------------
uint32_t MurmurHash2 ( const void * key, int len, uint32_t seed )
{
// 'm' and 'r' are mixing constants generated offline.
// They're not really 'magic', they just happen to work well.
const uint32_t m = 0x5bd1e995;
const int r = 24;
// Initialize the hash to a 'random' value
uint32_t h = seed ^ len;
// Mix 4 bytes at a time into the hash
const unsigned char * data = (const unsigned char *)key;
while(len >= 4)
{
uint32_t k = *(uint32_t*)data;
k *= m;
k ^= k >> r;
k *= m;
h *= m;
h ^= k;
data += 4;
len -= 4;
}
// Handle the last few bytes of the input array
switch(len)
{
case 3: h ^= data[2] << 16;
case 2: h ^= data[1] << 8;
case 1: h ^= data[0];
h *= m;
};
// Do a few final mixes of the hash to ensure the last few
// bytes are well-incorporated.
h ^= h >> 13;
h *= m;
h ^= h >> 15;
return h;
}
//-----------------------------------------------------------------------------
// MurmurHash2, 64-bit versions, by Austin Appleby
// The same caveats as 32-bit MurmurHash2 apply here - beware of alignment
// and endian-ness issues if used across multiple platforms.
// 64-bit hash for 64-bit platforms
uint64_t MurmurHash64A ( const void * key, int len, uint64_t seed )
{
const uint64_t m = BIG_CONSTANT(0xc6a4a7935bd1e995);
const int r = 47;
uint64_t h = seed ^ (len * m);
const uint64_t * data = (const uint64_t *)key;
const uint64_t * end = data + (len/8);
while(data != end)
{
uint64_t k = *data++;
k *= m;
k ^= k >> r;
k *= m;
h ^= k;
h *= m;
}
const unsigned char * data2 = (const unsigned char*)data;
switch(len & 7)
{
case 7: h ^= uint64_t(data2[6]) << 48;
case 6: h ^= uint64_t(data2[5]) << 40;
case 5: h ^= uint64_t(data2[4]) << 32;
case 4: h ^= uint64_t(data2[3]) << 24;
case 3: h ^= uint64_t(data2[2]) << 16;
case 2: h ^= uint64_t(data2[1]) << 8;
case 1: h ^= uint64_t(data2[0]);
h *= m;
};
h ^= h >> r;
h *= m;
h ^= h >> r;
return h;
}
// 64-bit hash for 32-bit platforms
uint64_t MurmurHash64B ( const void * key, int len, uint64_t seed )
{
const uint32_t m = 0x5bd1e995;
const int r = 24;
uint32_t h1 = uint32_t(seed) ^ len;
uint32_t h2 = uint32_t(seed >> 32);
const uint32_t * data = (const uint32_t *)key;
while(len >= 8)
{
uint32_t k1 = *data++;
k1 *= m; k1 ^= k1 >> r; k1 *= m;
h1 *= m; h1 ^= k1;
len -= 4;
uint32_t k2 = *data++;
k2 *= m; k2 ^= k2 >> r; k2 *= m;
h2 *= m; h2 ^= k2;
len -= 4;
}
if(len >= 4)
{
uint32_t k1 = *data++;
k1 *= m; k1 ^= k1 >> r; k1 *= m;
h1 *= m; h1 ^= k1;
len -= 4;
}
switch(len)
{
case 3: h2 ^= ((unsigned char*)data)[2] << 16;
case 2: h2 ^= ((unsigned char*)data)[1] << 8;
case 1: h2 ^= ((unsigned char*)data)[0];
h2 *= m;
};
h1 ^= h2 >> 18; h1 *= m;
h2 ^= h1 >> 22; h2 *= m;
h1 ^= h2 >> 17; h1 *= m;
h2 ^= h1 >> 19; h2 *= m;
uint64_t h = h1;
h = (h << 32) | h2;
return h;
}
//-----------------------------------------------------------------------------
// MurmurHash2A, by Austin Appleby
// This is a variant of MurmurHash2 modified to use the Merkle-Damgard
// construction. Bulk speed should be identical to Murmur2, small-key speed
// will be 10%-20% slower due to the added overhead at the end of the hash.
// This variant fixes a minor issue where null keys were more likely to
// collide with each other than expected, and also makes the function
// more amenable to incremental implementations.
#define mmix(h,k) { k *= m; k ^= k >> r; k *= m; h *= m; h ^= k; }
uint32_t MurmurHash2A ( const void * key, int len, uint32_t seed )
{
const uint32_t m = 0x5bd1e995;
const int r = 24;
uint32_t l = len;
const unsigned char * data = (const unsigned char *)key;
uint32_t h = seed;
while(len >= 4)
{
uint32_t k = *(uint32_t*)data;
mmix(h,k);
data += 4;
len -= 4;
}
uint32_t t = 0;
switch(len)
{
case 3: t ^= data[2] << 16;
case 2: t ^= data[1] << 8;
case 1: t ^= data[0];
};
mmix(h,t);
mmix(h,l);
h ^= h >> 13;
h *= m;
h ^= h >> 15;
return h;
}
//-----------------------------------------------------------------------------
// CMurmurHash2A, by Austin Appleby
// This is a sample implementation of MurmurHash2A designed to work
// incrementally.
// Usage -
// CMurmurHash2A hasher
// hasher.Begin(seed);
// hasher.Add(data1,size1);
// hasher.Add(data2,size2);
// ...
// hasher.Add(dataN,sizeN);
// uint32_t hash = hasher.End()
class CMurmurHash2A
{
public:
void Begin ( uint32_t seed = 0 )
{
m_hash = seed;
m_tail = 0;
m_count = 0;
m_size = 0;
}
void Add ( const unsigned char * data, int len )
{
m_size += len;
MixTail(data,len);
while(len >= 4)
{
uint32_t k = *(uint32_t*)data;
mmix(m_hash,k);
data += 4;
len -= 4;
}
MixTail(data,len);
}
uint32_t End ( void )
{
mmix(m_hash,m_tail);
mmix(m_hash,m_size);
m_hash ^= m_hash >> 13;
m_hash *= m;
m_hash ^= m_hash >> 15;
return m_hash;
}
private:
static const uint32_t m = 0x5bd1e995;
static const int r = 24;
void MixTail ( const unsigned char * & data, int & len )
{
while( len && ((len<4) || m_count) )
{
m_tail |= (*data++) << (m_count * 8);
m_count++;
len--;
if(m_count == 4)
{
mmix(m_hash,m_tail);
m_tail = 0;
m_count = 0;
}
}
}
uint32_t m_hash;
uint32_t m_tail;
uint32_t m_count;
uint32_t m_size;
};
//-----------------------------------------------------------------------------
// MurmurHashNeutral2, by Austin Appleby
// Same as MurmurHash2, but endian- and alignment-neutral.
// Half the speed though, alas.
uint32_t MurmurHashNeutral2 ( const void * key, int len, uint32_t seed )
{
const uint32_t m = 0x5bd1e995;
const int r = 24;
uint32_t h = seed ^ len;
const unsigned char * data = (const unsigned char *)key;
while(len >= 4)
{
uint32_t k;
k = data[0];
k |= data[1] << 8;
k |= data[2] << 16;
k |= data[3] << 24;
k *= m;
k ^= k >> r;
k *= m;
h *= m;
h ^= k;
data += 4;
len -= 4;
}
switch(len)
{
case 3: h ^= data[2] << 16;
case 2: h ^= data[1] << 8;
case 1: h ^= data[0];
h *= m;
};
h ^= h >> 13;
h *= m;
h ^= h >> 15;
return h;
}
//-----------------------------------------------------------------------------
// MurmurHashAligned2, by Austin Appleby
// Same algorithm as MurmurHash2, but only does aligned reads - should be safer
// on certain platforms.
// Performance will be lower than MurmurHash2
#define MIX(h,k,m) { k *= m; k ^= k >> r; k *= m; h *= m; h ^= k; }
uint32_t MurmurHashAligned2 ( const void * key, int len, uint32_t seed )
{
const uint32_t m = 0x5bd1e995;
const int r = 24;
const unsigned char * data = (const unsigned char *)key;
uint32_t h = seed ^ len;
int align = (uint64_t)data & 3;
if(align && (len >= 4))
{
// Pre-load the temp registers
uint32_t t = 0, d = 0;
switch(align)
{
case 1: t |= data[2] << 16;
case 2: t |= data[1] << 8;
case 3: t |= data[0];
}
t <<= (8 * align);
data += 4-align;
len -= 4-align;
int sl = 8 * (4-align);
int sr = 8 * align;
// Mix
while(len >= 4)
{
d = *(uint32_t *)data;
t = (t >> sr) | (d << sl);
uint32_t k = t;
MIX(h,k,m);
t = d;
data += 4;
len -= 4;
}
// Handle leftover data in temp registers
d = 0;
if(len >= align)
{
switch(align)
{
case 3: d |= data[2] << 16;
case 2: d |= data[1] << 8;
case 1: d |= data[0];
}
uint32_t k = (t >> sr) | (d << sl);
MIX(h,k,m);
data += align;
len -= align;
//----------
// Handle tail bytes
switch(len)
{
case 3: h ^= data[2] << 16;
case 2: h ^= data[1] << 8;
case 1: h ^= data[0];
h *= m;
};
}
else
{
switch(len)
{
case 3: d |= data[2] << 16;
case 2: d |= data[1] << 8;
case 1: d |= data[0];
case 0: h ^= (t >> sr) | (d << sl);
h *= m;
}
}
h ^= h >> 13;
h *= m;
h ^= h >> 15;
return h;
}
else
{
while(len >= 4)
{
uint32_t k = *(uint32_t *)data;
MIX(h,k,m);
data += 4;
len -= 4;
}
//----------
// Handle tail bytes
switch(len)
{
case 3: h ^= data[2] << 16;
case 2: h ^= data[1] << 8;
case 1: h ^= data[0];
h *= m;
};
h ^= h >> 13;
h *= m;
h ^= h >> 15;
return h;
}
}
//-----------------------------------------------------------------------------
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2016 Sultan Tarimo
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
@@ -0,0 +1,50 @@
# SITE-07 修改版源码与原作者署名
修改前 HEAD:d2a83f8a69c7a5d9a8bf30c9b370e573034f2000。继续控制台内嵌来源
核查;本批不改任何站点运行时、公开API、包版本或锁文件。
## 来源与实现
replicator 属于修改过的1.0.x源码家族,不能称为原样安装某个npm版本。其固定
console-feed提交de41ef2662019c645a652199d9bdbbfc71419f5e中的TS源码,使用
TypeScript4.1.2、ES3/CommonJS/LF生成,与npm3.2.2的运行代码逐字节一致;唯一
排除的是末尾原有inline source map。当前TS5.9.3会改变模板字符串的编译方式,
不能拿它的输出当作历史源码不匹配。原作者Ivan Nikulin的MIT许可从1.0.1保存,
明确这是修改版来源署名,不声称恢复唯一上游基点或原安装锁。
Emotion Stylis0.8.5对应Git tag提交6dd425bd1b8db7ab5144cca81b592639a68af2cb,
src/stylis.min.js与npm归档逐字节一致,package.json明确固定Stylis3.5.4。
上游build.js修改原始Stylis后请求在线Closure服务;保存这一历史配方与源码,
不执行过时服务,也不声称该更早阶段已重新构建。补齐Sultan Tarimo的MIT全文。
cache源码显式链接rule-sheet来源,已有Sultan完整注释继续保留并验证。
Emotion hash的两个显式来源分别为Gary Court的murmurhash-js与Austin Appleby
的MurmurHash2。Gary于2011年提交的README含完整MIT文本;Austin固定提交的CPP
顶部含作者署名及public-domain声明。保存源文件及原样截取声明,不用外层Emotion
许可替代这些作者信息。
attribution.ts负责Git内容/对象身份校验和修改版输出边界,reproduce.ts负责调度。
所有固定Git内容同时校验SHA-256和实际Git blob SHA-1,联网读取的base64响应也
走相同校验。历史TS编译器9,002,076字节,成员读取上限由8提升为16MiB;只在
忽略的复现缓存加载,不安装为项目依赖。新增4份公开notice,console共42份、
全站60份,加总索引61输出;生成器防遗漏保护同步更新。
## 验证与剩余范围
- Node24.21.0,Yarn1.22.22策略不变;24/24单元通过,增加Git对象错误、修改
内容、错误API编码、缺正文,以及只允许末尾source map差异的反例。
- docs-tools严格TS和相关lint通过;console及notices只读生成校验保持。
- 离线完整复现通过:原100模块/Parcel/包边、17map源/7tokenizer、5个固定Git
来源、replicator运行代码和Emotion发布源码匹配。联网及三浏览器交付细节见
[验证记录](../baselines/console-derived-validation.json)。
- 浏览器使用本地真实页面与媒体,逐字节比较60份许可,并验证移动日志、播放及
销毁。外部HTTPS由夹具隔离,不代表手机、远端CI或发布验收。
Chromium诊断包含一次pattern.mp4的ERR_ABORTED,媒体播放断言通过;没有
未处理页面错误或console error。记录未包含请求失败时间,不推断具体取消时刻。
来源台账为[derived attribution](../baselines/console-derived-attribution.json)。
控制台仍需处理Component的Stack Overflow引用与最终内嵌清查,VENDOR-08保留
open;SITE-07及其他Monaco/字体/媒体范围仍未完成,状态为doing,199/265不变。
回退移除本批4个notice及额外来源/复现步骤,恢复38份console清单,不影响此前
控制台修复。独立本地检查点提交,没有推送、部署或发布。
+1 -1
View File
@@ -653,7 +653,7 @@
- SITE-AI-DOCS-01: [记录](changes/2026-09-14-SITE-AI-DOCS-01-documentation-pipeline.md) [记录](baselines/documentation-pipeline-validation.json)
- SITE-BUILD-01: [记录](changes/2026-09-14-SITE-BUILD-01-staged-builds.md) [记录](baselines/site-build-validation.json)
- SITE-03: [记录](changes/2026-09-14-SITE-03-desktop-editor.md) [记录](baselines/site-editor-validation.json)
- SITE-07: [记录](site-inventory.md) [记录](baselines/site-provenance.json) [记录](changes/2026-09-14-SITE-07-vendor-notices.md) [记录](baselines/site-notices-checkpoint.json) [记录](baselines/site-codicons-provenance.json) [记录](baselines/site-codicons-validation.json) [记录](changes/2026-09-15-SITE-07-codicons.md) [记录](baselines/vconsole-notices-provenance.json) [记录](baselines/vconsole-notices-validation.json) [记录](changes/2026-09-15-SITE-07-vconsole-notices.md) [记录](console-modernization.md) [记录](baselines/site-console-inventory.json) [记录](baselines/site-console-validation.json) [记录](changes/2026-09-15-SITE-07-console-baseline.md) [记录](baselines/console-feed-provenance.json) [记录](changes/2026-09-15-SITE-07-console-feed-source.md) [记录](baselines/console-commonjs-provenance.json) [记录](changes/2026-09-15-SITE-07-console-commonjs.md) [记录](baselines/console-esm-provenance.json) [记录](changes/2026-09-15-SITE-07-console-esm.md) [记录](baselines/console-embedded-notices.json) [记录](baselines/console-notices-validation.json) [记录](changes/2026-09-15-SITE-07-console-notices.md) [记录](baselines/console-embedded-sources.json) [记录](baselines/console-embedded-validation.json) [记录](changes/2026-09-15-SITE-07-console-embedded-sources.md)
- SITE-07: [记录](site-inventory.md) [记录](baselines/site-provenance.json) [记录](changes/2026-09-14-SITE-07-vendor-notices.md) [记录](baselines/site-notices-checkpoint.json) [记录](baselines/site-codicons-provenance.json) [记录](baselines/site-codicons-validation.json) [记录](changes/2026-09-15-SITE-07-codicons.md) [记录](baselines/vconsole-notices-provenance.json) [记录](baselines/vconsole-notices-validation.json) [记录](changes/2026-09-15-SITE-07-vconsole-notices.md) [记录](console-modernization.md) [记录](baselines/site-console-inventory.json) [记录](baselines/site-console-validation.json) [记录](changes/2026-09-15-SITE-07-console-baseline.md) [记录](baselines/console-feed-provenance.json) [记录](changes/2026-09-15-SITE-07-console-feed-source.md) [记录](baselines/console-commonjs-provenance.json) [记录](changes/2026-09-15-SITE-07-console-commonjs.md) [记录](baselines/console-esm-provenance.json) [记录](changes/2026-09-15-SITE-07-console-esm.md) [记录](baselines/console-embedded-notices.json) [记录](baselines/console-notices-validation.json) [记录](changes/2026-09-15-SITE-07-console-notices.md) [记录](baselines/console-embedded-sources.json) [记录](baselines/console-embedded-validation.json) [记录](changes/2026-09-15-SITE-07-console-embedded-sources.md) [记录](baselines/console-derived-attribution.json) [记录](baselines/console-derived-validation.json) [记录](changes/2026-09-15-SITE-07-console-derived-attribution.md)
- EX-01: [记录](changes/2026-09-14-EX-01-react-consumer.md) [记录](baselines/react-consumer-validation.json) [记录](scripts/react-consumer.mjs)
- EX-02: [记录](changes/2026-09-14-EX-02-vue-consumer.md) [记录](baselines/vue-consumer-validation.json) [记录](scripts/vue-consumer.mjs)
- MOD-01: [记录](changes/2026-09-15-MOD-01-bun-evaluation.md) [记录](baselines/bun-install-validation.json) [记录](bun-evaluation.md)
+9
View File
@@ -1,5 +1,14 @@
# 进度与证据
## SITE-07 修改版 replicator 与 Emotion 署名
固定TS源码重现replicator运行代码,Emotion Stylis发布源码匹配Git tag;补齐
Ivan Nikulin、Sultan Tarimo、Gary Court和Austin Appleby的许可/声明。单元24/24,
联网/离线复现及三引擎实际交付3/3通过。
见[记录](changes/2026-09-15-SITE-07-console-derived-attribution.md)。不声称重跑旧
Closure服务或恢复完整原锁。控制台剩Stack Overflow引用及最终清查,其他站点
资产继续待审;VENDOR-08 open、SITE-07 doing,仍199/265,运行时和锁未改。
## SITE-07 三项内嵌依赖来源与许可
react-inspector中的Babel16文件、regenerator1文件及tokenizer7文件已逐字节
+6 -2
View File
@@ -699,11 +699,15 @@
"refactor/baselines/console-embedded-sources.json",
"refactor/baselines/console-embedded-validation.json",
"refactor/changes/2026-09-15-SITE-07-console-embedded-sources.md",
"scripts/site-vendor/console/embedded-sources.ts"
"scripts/site-vendor/console/embedded-sources.ts",
"refactor/baselines/console-derived-attribution.json",
"refactor/baselines/console-derived-validation.json",
"refactor/changes/2026-09-15-SITE-07-console-derived-attribution.md",
"scripts/site-vendor/console/attribution.ts"
],
"compatibleResolution": "Keep separate from owned TS migration. Verify source/version/diff and license notices before replacement; preserve API/CSS/worker URLs and run owning package tests.",
"closureCriteria": "固定上游版本/内容差异、完整组件许可与分发 notices,兼容测试通过;仅当前上游许可证名称不足以关闭。",
"workspaceState": "All 100 vendor module bodies and Parcel loader exactly reproduce from fixed archives. Additionally all 17 react-inspector external source-map members and seven tokenizer files match pinned upstream sources. Public console notices cover 38 entries; all 56 site notice files passed byte-for-byte HTTP checks in three engines. Remaining embedded attribution is tracked in console-embedded-notices.json. Original full lockfile is not recovered; runtime unchanged."
"workspaceState": "All 100 vendor modules and Parcel loader reproduce. Embedded inspector/tokenizer sources match; fixed replicator TS fork reproduces its archived runtime and Emotion Stylis source matches the immutable tag. Additional upstream author notices bring console notices to 42; all 60 site notice files passed HTTP byte checks in three engines. Stack Overflow attribution and final embedded review remain open. Original Closure service and full historical lockfile are not claimed; runtime unchanged."
},
{
"id": "SDK-01",
+4 -1
View File
@@ -4500,7 +4500,10 @@
"changes/2026-09-15-SITE-07-console-notices.md",
"baselines/console-embedded-sources.json",
"baselines/console-embedded-validation.json",
"changes/2026-09-15-SITE-07-console-embedded-sources.md"
"changes/2026-09-15-SITE-07-console-embedded-sources.md",
"baselines/console-derived-attribution.json",
"baselines/console-derived-validation.json",
"changes/2026-09-15-SITE-07-console-derived-attribution.md"
]
},
{