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",
|
||||
"@tomphttp/bare-server-node": "^2.0.3",
|
||||
"@types/eslint": "^8.56.10",
|
||||
"@types/estraverse": "^5.1.7",
|
||||
"@types/serviceworker": "^0.0.85",
|
||||
"@typescript-eslint/eslint-plugin": "^6.21.0",
|
||||
"@typescript-eslint/parser": "^6.21.0",
|
||||
|
@ -44,11 +45,11 @@
|
|||
"dependencies": {
|
||||
"@mercuryworkshop/bare-mux": "^2.0.2",
|
||||
"@webreflection/idb-map": "^0.3.1",
|
||||
"astravel": "^0.6.1",
|
||||
"astring": "^1.8.6",
|
||||
"dom-serializer": "^2.0.0",
|
||||
"domhandler": "^5.0.3",
|
||||
"domutils": "^3.1.0",
|
||||
"estraverse": "^5.3.0",
|
||||
"htmlparser2": "^9.1.0",
|
||||
"meriyah": "^4.4.2"
|
||||
}
|
||||
|
|
21
pnpm-lock.yaml
generated
21
pnpm-lock.yaml
generated
|
@ -14,9 +14,6 @@ importers:
|
|||
'@webreflection/idb-map':
|
||||
specifier: ^0.3.1
|
||||
version: 0.3.1
|
||||
astravel:
|
||||
specifier: ^0.6.1
|
||||
version: 0.6.1
|
||||
astring:
|
||||
specifier: ^1.8.6
|
||||
version: 1.8.6
|
||||
|
@ -29,6 +26,9 @@ importers:
|
|||
domutils:
|
||||
specifier: ^3.1.0
|
||||
version: 3.1.0
|
||||
estraverse:
|
||||
specifier: ^5.3.0
|
||||
version: 5.3.0
|
||||
htmlparser2:
|
||||
specifier: ^9.1.0
|
||||
version: 9.1.0
|
||||
|
@ -54,6 +54,9 @@ importers:
|
|||
'@types/eslint':
|
||||
specifier: ^8.56.10
|
||||
version: 8.56.10
|
||||
'@types/estraverse':
|
||||
specifier: ^5.1.7
|
||||
version: 5.1.7
|
||||
'@types/serviceworker':
|
||||
specifier: ^0.0.85
|
||||
version: 0.0.85
|
||||
|
@ -410,6 +413,9 @@ packages:
|
|||
'@types/eslint@8.56.10':
|
||||
resolution: {integrity: sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ==}
|
||||
|
||||
'@types/estraverse@5.1.7':
|
||||
resolution: {integrity: sha512-JRVtdKYZz7VkNp7hMC/WKoiZ8DS3byw20ZGoMZ1R8eBrBPIY7iBaDAS1zcrnXQCwK44G4vbXkimeU7R0VLG8UQ==}
|
||||
|
||||
'@types/estree@1.0.5':
|
||||
resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==}
|
||||
|
||||
|
@ -561,9 +567,6 @@ packages:
|
|||
resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
astravel@0.6.1:
|
||||
resolution: {integrity: sha512-ZIkgWFIV0Yo423Vqalz7VcF+BAiISvSgplnkV2abPGACPFKofsWTcvr9SFyYM/t/vMZWqmdP/Eze6ATX7r84Dg==}
|
||||
|
||||
astring@1.8.6:
|
||||
resolution: {integrity: sha512-ISvCdHdlTDlH5IpxQJIex7BWBywFWgjJSVdwst+/iQCoEYnyOaQ95+X1JGshuBjGp6nxKUy1jMgE3zPqN7fQdg==}
|
||||
hasBin: true
|
||||
|
@ -1692,6 +1695,10 @@ snapshots:
|
|||
'@types/estree': 1.0.5
|
||||
'@types/json-schema': 7.0.15
|
||||
|
||||
'@types/estraverse@5.1.7':
|
||||
dependencies:
|
||||
'@types/estree': 1.0.5
|
||||
|
||||
'@types/estree@1.0.5': {}
|
||||
|
||||
'@types/json-schema@7.0.15': {}
|
||||
|
@ -1853,8 +1860,6 @@ snapshots:
|
|||
|
||||
array-union@2.1.0: {}
|
||||
|
||||
astravel@0.6.1: {}
|
||||
|
||||
astring@1.8.6: {}
|
||||
|
||||
async-exit-hook@2.0.1: {}
|
||||
|
|
|
@ -29,7 +29,7 @@ function traverseParsedHtml(node, origin?: URL) {
|
|||
}
|
||||
|
||||
/* 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])) {
|
||||
const value = node.attribs[urlAttr];
|
||||
node.attribs[`data-${urlAttr}`] = value;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { parseModule } from "meriyah";
|
||||
import { generate } from "astring";
|
||||
import { makeTraveler } from "astravel";
|
||||
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
|
||||
|
||||
|
@ -18,10 +18,7 @@ import { encodeUrl } from "./url";
|
|||
|
||||
export function rewriteJs(js: string, origin?: URL) {
|
||||
try {
|
||||
const ast = parseModule(js, {
|
||||
module: true,
|
||||
webcompat: true
|
||||
});
|
||||
const ast = parseModule(js);
|
||||
|
||||
// const identifierList = [
|
||||
// "window",
|
||||
|
@ -33,30 +30,20 @@ export function rewriteJs(js: string, origin?: URL) {
|
|||
// ""
|
||||
// ]
|
||||
|
||||
const customTraveler = makeTraveler({
|
||||
ImportDeclaration: (node) => {
|
||||
node.source.value = encodeUrl(node.source.value, origin);
|
||||
replace(ast, {
|
||||
enter: (node, parent) => {
|
||||
if (["ImportDeclaration", "ImportExpression", "ExportAllDeclaration", "ExportNamedDeclaration"].includes(node.type) && node.source) {
|
||||
node.source.value = encodeUrl(node.source.value, origin);
|
||||
}
|
||||
|
||||
return node;
|
||||
},
|
||||
|
||||
ImportExpression: (node) => {
|
||||
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);
|
||||
fallback: "iteration"
|
||||
})
|
||||
|
||||
return generate(ast);
|
||||
} catch {
|
||||
console.log(js);
|
||||
|
||||
return js;
|
||||
} catch (err) {
|
||||
throw new Error(err);
|
||||
}
|
||||
}
|
|
@ -16,8 +16,11 @@ jsProperties.forEach((prop) => {
|
|||
const propDescriptor = Object.getOwnPropertyDescriptor(CSSStyleDeclaration.prototype, prop);
|
||||
|
||||
Object.defineProperty(CSSStyleDeclaration.prototype, prop, {
|
||||
get() {
|
||||
return propDescriptor.get.call(this);
|
||||
},
|
||||
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";
|
||||
|
||||
// object
|
||||
// iframe
|
||||
// embed
|
||||
// link
|
||||
// style
|
||||
// script
|
||||
// img
|
||||
// source
|
||||
// form
|
||||
// meta
|
||||
// area
|
||||
// base
|
||||
// body
|
||||
// input
|
||||
// audio
|
||||
// button
|
||||
// track
|
||||
// video
|
||||
|
||||
const attribs = {
|
||||
const attrObject = {
|
||||
"nonce": [HTMLElement],
|
||||
"integrity": [HTMLScriptElement, HTMLLinkElement],
|
||||
"csp": [HTMLIFrameElement],
|
||||
|
@ -30,64 +11,56 @@ const attribs = {
|
|||
"formaction": [HTMLButtonElement, HTMLInputElement],
|
||||
"srcdoc": [HTMLIFrameElement],
|
||||
"srcset": [HTMLImageElement, HTMLSourceElement],
|
||||
"imagesrcset": [HTMLLinkElement],
|
||||
"style": [HTMLElement]
|
||||
"imagesrcset": [HTMLLinkElement]
|
||||
}
|
||||
|
||||
Object.keys(attribs).forEach((attrib: string) => {
|
||||
attribs[attrib].forEach((element) => {
|
||||
const descriptor = Object.getOwnPropertyDescriptor(element.prototype, attrib);
|
||||
Object.defineProperty(element.prototype, attrib, {
|
||||
const attrs = Object.keys(attrObject);
|
||||
|
||||
for (const attr of attrs) {
|
||||
for (const element of attrObject[attr]) {
|
||||
const descriptor = Object.getOwnPropertyDescriptor(element.prototype, attr);
|
||||
Object.defineProperty(element.prototype, attr, {
|
||||
get() {
|
||||
return this.dataset[attrib];
|
||||
return this.dataset[attr];
|
||||
},
|
||||
|
||||
set(value) {
|
||||
this.dataset[attrib] = value;
|
||||
if (/nonce|integrity|csp/.test(attrib)) {
|
||||
this.removeAttribute(attrib);
|
||||
} else if (/src|href|data|action|formaction/.test(attrib)) {
|
||||
this.dataset[attr] = value;
|
||||
if (/nonce|integrity|csp/.test(attr)) {
|
||||
return;
|
||||
} else if (/src|href|data|action|formaction/.test(attr)) {
|
||||
// @ts-expect-error
|
||||
if (value instanceof TrustedScriptURL) {
|
||||
return;
|
||||
}
|
||||
|
||||
value = encodeUrl(value);
|
||||
} else if (attrib === "srcdoc") {
|
||||
} else if (attr === "srcdoc") {
|
||||
value = rewriteHtml(value);
|
||||
} else if (/(image)?srcset/.test(attrib)) {
|
||||
} else if (/(image)?srcset/.test(attr)) {
|
||||
value = rewriteSrcset(value);
|
||||
} else if (attrib === "style") {
|
||||
value = rewriteCss(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) {
|
||||
console.log(thisArg);
|
||||
if (Object.keys(attribs).includes(argArray[0])) {
|
||||
argArray[0] = `data-${argArray[0]}`;
|
||||
if (attrs.includes(argArray[0]) && thisArg.dataset[argArray[0]]) {
|
||||
return thisArg.dataset[argArray[0]];
|
||||
}
|
||||
|
||||
return Reflect.apply(target, thisArg, argArray);
|
||||
},
|
||||
});
|
||||
|
||||
// setAttribute proxy is currently broken
|
||||
|
||||
HTMLElement.prototype.setAttribute = new Proxy(Element.prototype.setAttribute, {
|
||||
Element.prototype.setAttribute = new Proxy(Element.prototype.setAttribute, {
|
||||
apply(target, thisArg, argArray) {
|
||||
if (thisArg.dataset["scramjet"]) {
|
||||
return;
|
||||
}
|
||||
console.log(argArray[1])
|
||||
if (Object.keys(attribs).includes(argArray[0])) {
|
||||
thisArg.dataset[`_${argArray[0]}`] = argArray[1];
|
||||
if (attrs.includes(argArray[0])) {
|
||||
thisArg.dataset[argArray[0]] = argArray[1];
|
||||
if (/nonce|integrity|csp/.test(argArray[0])) {
|
||||
return;
|
||||
} else if (/src|href|data|action|formaction/.test(argArray[0])) {
|
||||
|
@ -108,20 +81,16 @@ HTMLElement.prototype.setAttribute = new Proxy(Element.prototype.setAttribute, {
|
|||
|
||||
const innerHTML = Object.getOwnPropertyDescriptor(Element.prototype, "innerHTML");
|
||||
|
||||
Object.defineProperty(HTMLElement.prototype, "innerHTML", {
|
||||
Object.defineProperty(Element.prototype, "innerHTML", {
|
||||
set(value) {
|
||||
if (this instanceof HTMLScriptElement) {
|
||||
// @ts-expect-error
|
||||
if (!(value instanceof TrustedScript)) {
|
||||
value = rewriteJs(value);
|
||||
}
|
||||
// @ts-expect-error
|
||||
if (this instanceof HTMLScriptElement && !(value instanceof TrustedScript)) {
|
||||
value = rewriteJs(value);
|
||||
} else if (this instanceof HTMLStyleElement) {
|
||||
value = rewriteCss(value);
|
||||
} else {
|
||||
// @ts-expect-error
|
||||
if (!(value instanceof TrustedHTML)) {
|
||||
value = rewriteHtml(value);
|
||||
}
|
||||
// @ts-expect-error
|
||||
} else if (!(value instanceof TrustedHTML)) {
|
||||
value = rewriteHtml(value);
|
||||
}
|
||||
|
||||
return innerHTML.set.call(this, value);
|
||||
|
|
|
@ -7,7 +7,7 @@ import "./requests/websocket.ts"
|
|||
import "./element.ts";
|
||||
import "./storage.ts";
|
||||
import "./css.ts";
|
||||
import "./worker.ts"
|
||||
import "./worker.ts";
|
||||
|
||||
declare global {
|
||||
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