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

でリクエストをフックして

で直接実行してた

で変換して

なぜこんなものを作ろうと思ったのか……

Made with Slides.com