자 바스 크 립 트 의 순환 예 시 를 어떻게 검사 하 는 지 상세 하 게 설명 합 니 다.

머리말
만약 우리 가 사용자 가 쓴 코드 를 실행 해 야 한다 면,예 를 들 어 순환 을 피 하 는 것 과 같은 것 입 니까?우 리 는 최근 에 이 문 제 를 만 났 다.코드 를 잘못 쓰 는 것 이 흔 하기 때문에 시 도 를 해 보 았 다.

우선 iframe 을 사용 해 야 합 니 다.
이것 은 주로 안전 을 고려 하 는 것 입 니 다.우 리 는 전체 에 영향 을 주지 않도록 sandbox 환경 이 필요 합 니 다.iframe 의 Sandbox 속성 은 팝 업 창 을 금지 하 는 등 유용 합 니 다.
주 소 는 Blob url 을 선택 할 수 있 습 니 다.그러나 blob url 은 현재 웹 페이지 의 origin 을 가지 고 있 습 니 다.사용자 가 난잡 한 코드 를 복사 하여 실수 로 실행 하면 안전 에 문제 가 생 길 수 있 습 니 다.그래서 결국 data URI 로
iframe 의 실행 은 여전히 같은 thread 에 있 습 니 다.
iframe 에서 코드 를 실 행 했 습 니 다.순환 이 발생 했 을 때 브 라 우 저 는 죽 었 습 니 다.iframe 과 parent 는 같은 thread 에 있 기 때 문 입 니 다.즉,우 리 는 parent 에서 timeout 검 사 를 할 수 없습니다.검 측 코드 는 순환 이 발생 할 때 영원히 실행 되 지 않 기 때 문 입 니 다.
Web Worker 는 가능 하지만 DOM API 는 지원 되 지 않 습 니 다.
순수한 자 바스 크 립 트 코드 라면 웹 워 커 를 사용 할 수 있 지만 DOM API 가 필요 하기 때문에 웹 워 커 도 고려 하지 않 습 니 다.
사용자 코드 만 수정 할 수 있 을 것 같 습 니 다.
대부분의 순환 이 while/for 에 의 해 이 루어 진다 고 가정 합 니 다.만약 에 우리 가 코드 를 삽입 하고 모든 순환 에서 검 사 를 할 수 있다 면 우 리 는 특정한 조건 에 따라 순환 을 미리 중지 할 수 있 습 니 다.
예 를 들 면 이런 코드.

function abc() {
 while (true) {
  console.log(Date.now())
 }
}
하면,만약,만약...detectinfinite Loop()방법 을 while loop 에서 호출 하면 loop 10000 번 에서 오 류 를 보고 하여 실행 을 중지 할 수 있 습 니 다.

let __count = 0
const __detectInfiniteLoop = () => {
 if (__count > 10000) {
  throw new Error('Infinite Loop detected')
 }
 __count += 1
}

function abc() {
 while (true) {
  console.log(Date.now())
  __detectInfiniteLoop()
 }
}
조작 AST 적당 한 위치 에 코드 삽입
문자열 매 칭 을 통 해 코드 디 테 일 을 편집 하 는 것 은 너무 복잡 하고 오류 가 발생 하기 쉬 우 며,우 리 는 AST 를 편집 하 는 방식 으로 실제로는 매우 간단 하 다.
babel 을 위 한 패키지 3 개.
  • @babel/parser-parse 코드 는 AST
  • @babel/traverse-검색 for/while loop
  • @babel/generator-삽 입 된 코드 생 성
  • 우선 parse 사용자 의 코드 는 AST 입 니 다.
    
    import { parse } from '@babel/parser'
    const ast = parse(code)
    
    그리고 우 리 는 삽입 해 야 할 코드 를 준비 합 시다.
    코드 는 두 부분 이 있 습 니 다.첫 번 째 부분 은 function 정의 입 니 다.실제로 머리 에 삽입 할 수 있 기 때문에 문자열 이면 충분 합 니 다.두 번 째 부분 은 function 호출 입 니 다.이 부분 은 AST 에 삽입 해 야 하기 때문에 parse 도 필요 합 니 다.
    
    const prefix = `
     let __count = 0
     const __detectInfiniteLoop = () => {
      if (__count > 10000) {
       throw new Error('Infinite Loop detected')
      }
      __count += 1
     }
    `
    
    const detector = parse(`__detectInfiniteLoop()`)
    
    
    다음은 while/for/do.while 의 위 치 를 찾 아 detector 호출 을 삽입 합 니 다.
    
    import traverse from '@babel/traverse'
    traverse(ast, {
     ForStatement: function (path) {
      path.node.body.body.push(...detector.program.body)
     },
     WhileStatement: function (path) {
      path.node.body.body.push(...detector.program.body)
     },
     DoWhileStatement: function (path) {
      path.node.body.body.push(...detector.program.body)
     }
    })
    
    AST 가 수정 되 었 습 니 다.마지막 단 계 는 최종 코드 를 만 들 고 iframe 에서 실행 하 는 것 입 니 다.
    
    import generate from '@babel/generator'
    const newCode = prefix + generate(ast).code
    

    소원 성취!꽃 을 뿌 려 라!
    마지막.
    이 방법 은 완벽 한 것 은 아니 지만,우리 자신의 요 구 를 만족 시 켰 다.너 는 수요 에 따라 조정 을 진행 할 수 있다.
    자 바스 크 립 트 의 순환 을 어떻게 감지 하 는 지 에 관 한 이 글 은 여기까지 소개 되 었 습 니 다.자 바스 크 립 트 의 순환 을 감지 하 는 내용 은 예전 의 글 을 검색 하거나 아래 의 관련 글 을 계속 찾 아 보 세 요.앞으로 많은 응원 부탁드립니다!

    좋은 웹페이지 즐겨찾기