오픈 소스 모험: 에피소드 26: Imba 2 스택 오버플로

4910 단어 javascriptimba
Imba 1에서 Imba 2로 앱을 포팅하는 동안 Imba 2에서 버그를 만났지만 너무 바빠서 처리할 수 없었습니다. 한 걸음 물러서서 최소한의 사례로 버그를 재현한 다음 제출해 봅시다.

버그



버그는 코드에 debugger 문을 넣었을 때 위치에 따라 Imba가 오버플로를 쌓는 것이었습니다.

복제하기



어떤 앱에 이 문제가 있었는지 기억이 안나서 imba2-game-of-life 으로 먼저 해봐야겠습니다. 다행스럽게도 작동한다면 실행할 필요조차 없으며 터미널에서 분명할 것입니다.

그래서 client.imba를 열고 여러 곳에 debugger를 추가하기 시작했습니다.

블록 이후에 사용하는 모든 함수에서 충돌이 발생하는 데 시간이 전혀 걸리지 않았습니다. 예를 들면 다음과 같습니다.

def countNeighbours(cells, x, y)
  let count = 0
  for cell of cells
    if !cell.state
      continue
    let dx = Math.abs(cell.x - x)
    let dy = Math.abs(cell.y - y)
    if Math.max(dx, dy) == 1
      count += 1
  count

def runStep(cells)
  let nextCells = []
  for cell of cells
    let n = countNeighbours(cells, cell.x, cell.y)
    let nextState = (n == 3 || (cell.state && n == 2))
    nextCells.push({x: cell.x, y: cell.y, state: nextState})
  nextCells

tag cell
  prop data

  def onclick
    data.state = !data.state
    emit("pause")

  def render
    let visualStartX = 20 * data.x + 1
    let visualStartY = 20 * data.y + 1

    <self[left:{visualStartX}px top:{visualStartY}px] .alive=(data.state) .dead=(!data.state) @click.onclick>

  css
    position: absolute
    width: 18px
    height: 18px
    &.dead
      background-color: #864
    &.alive
      background-color: #3f3

tag app
  prop cells
  prop playing = true

  def setup
    let sizex = 30
    let sizey = 30
    cells = []
    for x in [0 ... sizex]
      for y in [0 ... sizey]
        cells.push({ x: x, y: y, state: Math.random() < 0.2 })

  def step
    cells = runStep(cells)

  def mount
    imba.setInterval(&,100) do
      if playing
        step()
    debugger

  def play
    playing = true

  def pause
    playing = false

  def render
    <self>
      <header>
        "Game of Life"
      <div.board>
        for cell in cells
          <cell data=cell @pause.pause>
      <div.buttons>
        if playing
          <button @click.pause>
            "Pause"
        else
          <button @click.step>
            "Step"
          <button @click.play>
            "Play"

  css
    header
      font-size: 64px
      text-align: center
    .board
      position: relative
      height: 600px
      width: 600px
      background-color: #aaa
      margin: auto
    .buttons
      text-align: center
    button
      margin: 0.5em

imba.mount <app>


터미널의 오류 메시지:

ERROR COMPILING IMBA RangeError: Maximum call stack size exceeded
    at Yp.J.consume (~/imba2-game-of-life/node_modules/imba/compiler.imba.js:79:11138)
    at Qe.c (~/imba2-game-of-life/node_modules/imba/compiler.imba.js:88:4768)
    at Qe.c (~/imba2-game-of-life/node_modules/imba/compiler.imba.js:88:4782)
    at Qe.c (~/imba2-game-of-life/node_modules/imba/compiler.imba.js:88:4782)
    at Qe.c (~/imba2-game-of-life/node_modules/imba/compiler.imba.js:88:4782)
    at Qe.c (~/imba2-game-of-life/node_modules/imba/compiler.imba.js:88:4782)
    at Qe.c (~/imba2-game-of-life/node_modules/imba/compiler.imba.js:88:4782)
    at Qe.c (~/imba2-game-of-life/node_modules/imba/compiler.imba.js:88:4782)
    at Qe.c (~/imba2-game-of-life/node_modules/imba/compiler.imba.js:88:4782)
    at Qe.c (~/imba2-game-of-life/node_modules/imba/compiler.imba.js:88:4782) app/client.imba


관련 없는 부분 제거



앱이 필요하지 않습니다. 명확한 테스트 케이스만 있으면 됩니다. 이제 모든 추가 항목을 제거할 시간입니다. 그리고 단계별로 충돌이 여전히 존재하는지 확인한 후 다음과 같은 결론에 도달했습니다.

def foo
  debugger


심지어 같은 충돌이 발생합니다.

버그를 유발하는 다른 방법 탐색



자, 이제 메서드 끝에 있는 debugger가 Imba 컴파일러와 충돌합니다. 그러나 나는 이것을 다른 맥락에서도 보았다고 확신합니다.

블록 끝에 debugger를 넣는 것처럼 보입니다.

def foo
  imba.setInterval(&,1000) do
    debugger


다른 맥락에서 이런 일이 일어나는 것을 본 것 같은데 지금 당장은 재현할 수 없습니다. 그래서 내가 잘못 기억하고 있는 것일 수도 있고, 어쨌든 이것에 대한 수정이 더 복잡한 경우도 다룰 수 있을 것입니다.

버그를 제출할 시간



다음 단계는 GitHub issues for Imba으로 이동하여 debugger를 검색하는 것입니다. 이전에 보고된 것 같지 않으므로 제출할 시간입니다.

늘 그렇듯이 미리 만들어진 템플릿은 유용한 것보다 짜증나는 것 같아서 삭제했습니다. So here's the bug report .

돌이켜보면 버그 보고서를 작성할 시간이 없었더라도 코딩하면서 실패한 코드를 저장했어야 했습니다.

다음에 온다



다음 에피소드에서는 Imba 2에 대한 몇 가지 생각을 전하겠습니다.

좋은 웹페이지 즐겨찾기