mirror of
https://github.com/MercuryWorkshop/scramjet.git
synced 2025-05-14 06:50:01 -04:00
convert to estraverse and minor cleanup
This commit is contained in:
parent
bc9a16720e
commit
29bbda0700
8 changed files with 66 additions and 126 deletions
|
@ -28,6 +28,7 @@
|
||||||
"@mercuryworkshop/libcurl-transport": "^1.3.6",
|
"@mercuryworkshop/libcurl-transport": "^1.3.6",
|
||||||
"@tomphttp/bare-server-node": "^2.0.3",
|
"@tomphttp/bare-server-node": "^2.0.3",
|
||||||
"@types/eslint": "^8.56.10",
|
"@types/eslint": "^8.56.10",
|
||||||
|
"@types/estraverse": "^5.1.7",
|
||||||
"@types/serviceworker": "^0.0.85",
|
"@types/serviceworker": "^0.0.85",
|
||||||
"@typescript-eslint/eslint-plugin": "^6.21.0",
|
"@typescript-eslint/eslint-plugin": "^6.21.0",
|
||||||
"@typescript-eslint/parser": "^6.21.0",
|
"@typescript-eslint/parser": "^6.21.0",
|
||||||
|
@ -44,11 +45,11 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@mercuryworkshop/bare-mux": "^2.0.2",
|
"@mercuryworkshop/bare-mux": "^2.0.2",
|
||||||
"@webreflection/idb-map": "^0.3.1",
|
"@webreflection/idb-map": "^0.3.1",
|
||||||
"astravel": "^0.6.1",
|
|
||||||
"astring": "^1.8.6",
|
"astring": "^1.8.6",
|
||||||
"dom-serializer": "^2.0.0",
|
"dom-serializer": "^2.0.0",
|
||||||
"domhandler": "^5.0.3",
|
"domhandler": "^5.0.3",
|
||||||
"domutils": "^3.1.0",
|
"domutils": "^3.1.0",
|
||||||
|
"estraverse": "^5.3.0",
|
||||||
"htmlparser2": "^9.1.0",
|
"htmlparser2": "^9.1.0",
|
||||||
"meriyah": "^4.4.2"
|
"meriyah": "^4.4.2"
|
||||||
}
|
}
|
||||||
|
|
21
pnpm-lock.yaml
generated
21
pnpm-lock.yaml
generated
|
@ -14,9 +14,6 @@ importers:
|
||||||
'@webreflection/idb-map':
|
'@webreflection/idb-map':
|
||||||
specifier: ^0.3.1
|
specifier: ^0.3.1
|
||||||
version: 0.3.1
|
version: 0.3.1
|
||||||
astravel:
|
|
||||||
specifier: ^0.6.1
|
|
||||||
version: 0.6.1
|
|
||||||
astring:
|
astring:
|
||||||
specifier: ^1.8.6
|
specifier: ^1.8.6
|
||||||
version: 1.8.6
|
version: 1.8.6
|
||||||
|
@ -29,6 +26,9 @@ importers:
|
||||||
domutils:
|
domutils:
|
||||||
specifier: ^3.1.0
|
specifier: ^3.1.0
|
||||||
version: 3.1.0
|
version: 3.1.0
|
||||||
|
estraverse:
|
||||||
|
specifier: ^5.3.0
|
||||||
|
version: 5.3.0
|
||||||
htmlparser2:
|
htmlparser2:
|
||||||
specifier: ^9.1.0
|
specifier: ^9.1.0
|
||||||
version: 9.1.0
|
version: 9.1.0
|
||||||
|
@ -54,6 +54,9 @@ importers:
|
||||||
'@types/eslint':
|
'@types/eslint':
|
||||||
specifier: ^8.56.10
|
specifier: ^8.56.10
|
||||||
version: 8.56.10
|
version: 8.56.10
|
||||||
|
'@types/estraverse':
|
||||||
|
specifier: ^5.1.7
|
||||||
|
version: 5.1.7
|
||||||
'@types/serviceworker':
|
'@types/serviceworker':
|
||||||
specifier: ^0.0.85
|
specifier: ^0.0.85
|
||||||
version: 0.0.85
|
version: 0.0.85
|
||||||
|
@ -410,6 +413,9 @@ packages:
|
||||||
'@types/eslint@8.56.10':
|
'@types/eslint@8.56.10':
|
||||||
resolution: {integrity: sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ==}
|
resolution: {integrity: sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ==}
|
||||||
|
|
||||||
|
'@types/estraverse@5.1.7':
|
||||||
|
resolution: {integrity: sha512-JRVtdKYZz7VkNp7hMC/WKoiZ8DS3byw20ZGoMZ1R8eBrBPIY7iBaDAS1zcrnXQCwK44G4vbXkimeU7R0VLG8UQ==}
|
||||||
|
|
||||||
'@types/estree@1.0.5':
|
'@types/estree@1.0.5':
|
||||||
resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==}
|
resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==}
|
||||||
|
|
||||||
|
@ -561,9 +567,6 @@ packages:
|
||||||
resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==}
|
resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
|
||||||
astravel@0.6.1:
|
|
||||||
resolution: {integrity: sha512-ZIkgWFIV0Yo423Vqalz7VcF+BAiISvSgplnkV2abPGACPFKofsWTcvr9SFyYM/t/vMZWqmdP/Eze6ATX7r84Dg==}
|
|
||||||
|
|
||||||
astring@1.8.6:
|
astring@1.8.6:
|
||||||
resolution: {integrity: sha512-ISvCdHdlTDlH5IpxQJIex7BWBywFWgjJSVdwst+/iQCoEYnyOaQ95+X1JGshuBjGp6nxKUy1jMgE3zPqN7fQdg==}
|
resolution: {integrity: sha512-ISvCdHdlTDlH5IpxQJIex7BWBywFWgjJSVdwst+/iQCoEYnyOaQ95+X1JGshuBjGp6nxKUy1jMgE3zPqN7fQdg==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
@ -1692,6 +1695,10 @@ snapshots:
|
||||||
'@types/estree': 1.0.5
|
'@types/estree': 1.0.5
|
||||||
'@types/json-schema': 7.0.15
|
'@types/json-schema': 7.0.15
|
||||||
|
|
||||||
|
'@types/estraverse@5.1.7':
|
||||||
|
dependencies:
|
||||||
|
'@types/estree': 1.0.5
|
||||||
|
|
||||||
'@types/estree@1.0.5': {}
|
'@types/estree@1.0.5': {}
|
||||||
|
|
||||||
'@types/json-schema@7.0.15': {}
|
'@types/json-schema@7.0.15': {}
|
||||||
|
@ -1853,8 +1860,6 @@ snapshots:
|
||||||
|
|
||||||
array-union@2.1.0: {}
|
array-union@2.1.0: {}
|
||||||
|
|
||||||
astravel@0.6.1: {}
|
|
||||||
|
|
||||||
astring@1.8.6: {}
|
astring@1.8.6: {}
|
||||||
|
|
||||||
async-exit-hook@2.0.1: {}
|
async-exit-hook@2.0.1: {}
|
||||||
|
|
|
@ -29,7 +29,7 @@ function traverseParsedHtml(node, origin?: URL) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* url attributes */
|
/* url attributes */
|
||||||
for (const urlAttr of ["src", "href", "data", "action"]) {
|
for (const urlAttr of ["src", "href", "data", "action", "formaction"]) {
|
||||||
if (hasAttrib(node, urlAttr) && !isScramjetFile(node.attribs[urlAttr])) {
|
if (hasAttrib(node, urlAttr) && !isScramjetFile(node.attribs[urlAttr])) {
|
||||||
const value = node.attribs[urlAttr];
|
const value = node.attribs[urlAttr];
|
||||||
node.attribs[`data-${urlAttr}`] = value;
|
node.attribs[`data-${urlAttr}`] = value;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { parseModule } from "meriyah";
|
import { parseModule } from "meriyah";
|
||||||
import { generate } from "astring";
|
import { generate } from "astring";
|
||||||
import { makeTraveler } from "astravel";
|
|
||||||
import { encodeUrl } from "./url";
|
import { encodeUrl } from "./url";
|
||||||
|
import { replace } from "estraverse";
|
||||||
|
|
||||||
// i am a cat. i like to be petted. i like to be fed. i like to be
|
// i am a cat. i like to be petted. i like to be fed. i like to be
|
||||||
|
|
||||||
|
@ -18,10 +18,7 @@ import { encodeUrl } from "./url";
|
||||||
|
|
||||||
export function rewriteJs(js: string, origin?: URL) {
|
export function rewriteJs(js: string, origin?: URL) {
|
||||||
try {
|
try {
|
||||||
const ast = parseModule(js, {
|
const ast = parseModule(js);
|
||||||
module: true,
|
|
||||||
webcompat: true
|
|
||||||
});
|
|
||||||
|
|
||||||
// const identifierList = [
|
// const identifierList = [
|
||||||
// "window",
|
// "window",
|
||||||
|
@ -33,30 +30,20 @@ export function rewriteJs(js: string, origin?: URL) {
|
||||||
// ""
|
// ""
|
||||||
// ]
|
// ]
|
||||||
|
|
||||||
const customTraveler = makeTraveler({
|
replace(ast, {
|
||||||
ImportDeclaration: (node) => {
|
enter: (node, parent) => {
|
||||||
|
if (["ImportDeclaration", "ImportExpression", "ExportAllDeclaration", "ExportNamedDeclaration"].includes(node.type) && node.source) {
|
||||||
node.source.value = encodeUrl(node.source.value, origin);
|
node.source.value = encodeUrl(node.source.value, origin);
|
||||||
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
},
|
},
|
||||||
|
|
||||||
ImportExpression: (node) => {
|
fallback: "iteration"
|
||||||
node.source.value = encodeUrl(node.source.value, origin);
|
})
|
||||||
},
|
|
||||||
|
|
||||||
ExportAllDeclaration: (node) => {
|
|
||||||
node.source.value = encodeUrl(node.source.value, origin);
|
|
||||||
},
|
|
||||||
|
|
||||||
ExportNamedDeclaration: (node) => {
|
|
||||||
if (node.source) node.source.value = encodeUrl(node.source.value, origin);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
customTraveler.go(ast);
|
|
||||||
|
|
||||||
return generate(ast);
|
return generate(ast);
|
||||||
} catch {
|
} catch (err) {
|
||||||
console.log(js);
|
throw new Error(err);
|
||||||
|
|
||||||
return js;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -16,8 +16,11 @@ jsProperties.forEach((prop) => {
|
||||||
const propDescriptor = Object.getOwnPropertyDescriptor(CSSStyleDeclaration.prototype, prop);
|
const propDescriptor = Object.getOwnPropertyDescriptor(CSSStyleDeclaration.prototype, prop);
|
||||||
|
|
||||||
Object.defineProperty(CSSStyleDeclaration.prototype, prop, {
|
Object.defineProperty(CSSStyleDeclaration.prototype, prop, {
|
||||||
|
get() {
|
||||||
|
return propDescriptor.get.call(this);
|
||||||
|
},
|
||||||
set(v) {
|
set(v) {
|
||||||
propDescriptor.set.call(this, rewriteCss(v));
|
return propDescriptor.set.call(this, rewriteCss(v));
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
});
|
});
|
|
@ -1,25 +1,6 @@
|
||||||
import { encodeUrl, rewriteCss, rewriteHtml, rewriteJs, rewriteSrcset } from "../bundle";
|
import { encodeUrl, rewriteCss, rewriteHtml, rewriteJs, rewriteSrcset } from "../bundle";
|
||||||
|
|
||||||
// object
|
const attrObject = {
|
||||||
// iframe
|
|
||||||
// embed
|
|
||||||
// link
|
|
||||||
// style
|
|
||||||
// script
|
|
||||||
// img
|
|
||||||
// source
|
|
||||||
// form
|
|
||||||
// meta
|
|
||||||
// area
|
|
||||||
// base
|
|
||||||
// body
|
|
||||||
// input
|
|
||||||
// audio
|
|
||||||
// button
|
|
||||||
// track
|
|
||||||
// video
|
|
||||||
|
|
||||||
const attribs = {
|
|
||||||
"nonce": [HTMLElement],
|
"nonce": [HTMLElement],
|
||||||
"integrity": [HTMLScriptElement, HTMLLinkElement],
|
"integrity": [HTMLScriptElement, HTMLLinkElement],
|
||||||
"csp": [HTMLIFrameElement],
|
"csp": [HTMLIFrameElement],
|
||||||
|
@ -30,64 +11,56 @@ const attribs = {
|
||||||
"formaction": [HTMLButtonElement, HTMLInputElement],
|
"formaction": [HTMLButtonElement, HTMLInputElement],
|
||||||
"srcdoc": [HTMLIFrameElement],
|
"srcdoc": [HTMLIFrameElement],
|
||||||
"srcset": [HTMLImageElement, HTMLSourceElement],
|
"srcset": [HTMLImageElement, HTMLSourceElement],
|
||||||
"imagesrcset": [HTMLLinkElement],
|
"imagesrcset": [HTMLLinkElement]
|
||||||
"style": [HTMLElement]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.keys(attribs).forEach((attrib: string) => {
|
const attrs = Object.keys(attrObject);
|
||||||
attribs[attrib].forEach((element) => {
|
|
||||||
const descriptor = Object.getOwnPropertyDescriptor(element.prototype, attrib);
|
for (const attr of attrs) {
|
||||||
Object.defineProperty(element.prototype, attrib, {
|
for (const element of attrObject[attr]) {
|
||||||
|
const descriptor = Object.getOwnPropertyDescriptor(element.prototype, attr);
|
||||||
|
Object.defineProperty(element.prototype, attr, {
|
||||||
get() {
|
get() {
|
||||||
return this.dataset[attrib];
|
return this.dataset[attr];
|
||||||
},
|
},
|
||||||
|
|
||||||
set(value) {
|
set(value) {
|
||||||
this.dataset[attrib] = value;
|
this.dataset[attr] = value;
|
||||||
if (/nonce|integrity|csp/.test(attrib)) {
|
if (/nonce|integrity|csp/.test(attr)) {
|
||||||
this.removeAttribute(attrib);
|
return;
|
||||||
} else if (/src|href|data|action|formaction/.test(attrib)) {
|
} else if (/src|href|data|action|formaction/.test(attr)) {
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
if (value instanceof TrustedScriptURL) {
|
if (value instanceof TrustedScriptURL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
value = encodeUrl(value);
|
value = encodeUrl(value);
|
||||||
} else if (attrib === "srcdoc") {
|
} else if (attr === "srcdoc") {
|
||||||
value = rewriteHtml(value);
|
value = rewriteHtml(value);
|
||||||
} else if (/(image)?srcset/.test(attrib)) {
|
} else if (/(image)?srcset/.test(attr)) {
|
||||||
value = rewriteSrcset(value);
|
value = rewriteSrcset(value);
|
||||||
} else if (attrib === "style") {
|
|
||||||
value = rewriteCss(value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
descriptor.set.call(this, value);
|
descriptor.set.call(this, value);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
})
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
HTMLElement.prototype.getAttribute = new Proxy(Element.prototype.getAttribute, {
|
Element.prototype.getAttribute = new Proxy(Element.prototype.getAttribute, {
|
||||||
apply(target, thisArg, argArray) {
|
apply(target, thisArg, argArray) {
|
||||||
console.log(thisArg);
|
if (attrs.includes(argArray[0]) && thisArg.dataset[argArray[0]]) {
|
||||||
if (Object.keys(attribs).includes(argArray[0])) {
|
return thisArg.dataset[argArray[0]];
|
||||||
argArray[0] = `data-${argArray[0]}`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Reflect.apply(target, thisArg, argArray);
|
return Reflect.apply(target, thisArg, argArray);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
// setAttribute proxy is currently broken
|
Element.prototype.setAttribute = new Proxy(Element.prototype.setAttribute, {
|
||||||
|
|
||||||
HTMLElement.prototype.setAttribute = new Proxy(Element.prototype.setAttribute, {
|
|
||||||
apply(target, thisArg, argArray) {
|
apply(target, thisArg, argArray) {
|
||||||
if (thisArg.dataset["scramjet"]) {
|
if (attrs.includes(argArray[0])) {
|
||||||
return;
|
thisArg.dataset[argArray[0]] = argArray[1];
|
||||||
}
|
|
||||||
console.log(argArray[1])
|
|
||||||
if (Object.keys(attribs).includes(argArray[0])) {
|
|
||||||
thisArg.dataset[`_${argArray[0]}`] = argArray[1];
|
|
||||||
if (/nonce|integrity|csp/.test(argArray[0])) {
|
if (/nonce|integrity|csp/.test(argArray[0])) {
|
||||||
return;
|
return;
|
||||||
} else if (/src|href|data|action|formaction/.test(argArray[0])) {
|
} else if (/src|href|data|action|formaction/.test(argArray[0])) {
|
||||||
|
@ -108,21 +81,17 @@ HTMLElement.prototype.setAttribute = new Proxy(Element.prototype.setAttribute, {
|
||||||
|
|
||||||
const innerHTML = Object.getOwnPropertyDescriptor(Element.prototype, "innerHTML");
|
const innerHTML = Object.getOwnPropertyDescriptor(Element.prototype, "innerHTML");
|
||||||
|
|
||||||
Object.defineProperty(HTMLElement.prototype, "innerHTML", {
|
Object.defineProperty(Element.prototype, "innerHTML", {
|
||||||
set(value) {
|
set(value) {
|
||||||
if (this instanceof HTMLScriptElement) {
|
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
if (!(value instanceof TrustedScript)) {
|
if (this instanceof HTMLScriptElement && !(value instanceof TrustedScript)) {
|
||||||
value = rewriteJs(value);
|
value = rewriteJs(value);
|
||||||
}
|
|
||||||
} else if (this instanceof HTMLStyleElement) {
|
} else if (this instanceof HTMLStyleElement) {
|
||||||
value = rewriteCss(value);
|
value = rewriteCss(value);
|
||||||
} else {
|
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
if (!(value instanceof TrustedHTML)) {
|
} else if (!(value instanceof TrustedHTML)) {
|
||||||
value = rewriteHtml(value);
|
value = rewriteHtml(value);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return innerHTML.set.call(this, value);
|
return innerHTML.set.call(this, value);
|
||||||
},
|
},
|
||||||
|
|
|
@ -7,7 +7,7 @@ import "./requests/websocket.ts"
|
||||||
import "./element.ts";
|
import "./element.ts";
|
||||||
import "./storage.ts";
|
import "./storage.ts";
|
||||||
import "./css.ts";
|
import "./css.ts";
|
||||||
import "./worker.ts"
|
import "./worker.ts";
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface Window {
|
interface Window {
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
export default class Clone {
|
|
||||||
el: HTMLElement;
|
|
||||||
copy: HTMLElement
|
|
||||||
|
|
||||||
constructor(element: HTMLElement) {
|
|
||||||
this.el = element;
|
|
||||||
this.copy = document.createElement(element.tagName);
|
|
||||||
|
|
||||||
for (const attr of element.getAttributeNames()) {
|
|
||||||
this.copy.setAttribute(attr, element.getAttribute(attr));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (element.innerHTML) {
|
|
||||||
this.copy.innerHTML = element.innerHTML;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
insertCopy() {
|
|
||||||
this.el.insertAdjacentElement("afterend", this.copy);
|
|
||||||
}
|
|
||||||
|
|
||||||
removeElement() {
|
|
||||||
this.el.remove();
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Add table
Add a link
Reference in a new issue