FromJS の黒魔術を
読み解く
Roppongi.js #3
@ktsn
HTML 内の文字列から元のソースの場所がわかる???
🤔
そんなの JS の機能にあったっけ……
new Error().stack
// Error
// at <anonymous>:1:1"
どこでセットされたのかを知る
var originalInnerHTMLDescriptor = Object.getOwnPropertyDescriptor(
Element.prototype,
"innerHTML"
)
Object.defineProperty(Element.prototype, "innerHTML", {
set: function(html){
this.__innerHTMLOrigin = {
action: "Assign InnerHTML",
value: "Hello World!",
stack: new Error().stack,
inputValues: [html],
}
return originalInnerHTMLDescriptor.set.apply(this, arguments)
}
})
セットされた瞬間だけでは不十分では?
var greeting = "Hello"
greeting += " World!"
var el = document.getElementById("welcome")
el.innerHTML = greeting
Babel プラグインを書いてリテラルを
差し替える
var greeting = f__StringLiteral("Hello")
greeting = f__add(greeting, " World!")
var el = document.getElementById("welcome")
el.innerHTML = greeting
{
action: "Concatenate String",
value: "Hello World!",
stack: `Error
at f__add (http://localhost:1234/from.js:93754:22)
at http://localhost:1234/example.js:2:12`,
inputValues: [
{
action: "String Literal",
value: "Hello"
stack: `Error
at f__StringLiteral (http://localhost:1234/from.js:93709:22)
at http://localhost:1234/example.js:1:16`,
inputValues: []
},
{
action: "String Literal",
value: " World!",
stack: `Error
at f__StringLiteral (http://localhost:7500/from.js:93709:22)
at http://localhost:1234/example.js:2:29`,
inputValues: []
}
]
}
el.innerHTML = {
action: "Concatenate String",
value: "Hello World!",
stack: `Error
at f__add (http://localhost:1234/from.js:93754:22)
at http://localhost:1234/example.js:2:12`,
inputValues: []
}
toString をつけて文字列として
扱われるようにしておく
el.innerHTML = {
action: "Concatenate String",
value: "Hello World!",
stack: `Error
at f__add (http://localhost:1234/from.js:93754:22)
at http://localhost:1234/example.js:2:12`,
inputValues: [],
toString: function() {
return this.value
}
}
chrome.tabs.executeScript
chrome.webRequest.onBeforeRequest.addListener
でリクエストをフックして
で直接実行してた
で変換して
なぜこんなものを作ろうと思ったのか……
FromJS の黒魔術を読み解く
By katashin