// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Flags: --validate-asm --allow-natives-syntax

let {session, contextGroup, Protocol} = InspectorTest.start(
    'This test runs asm.js which calls back to JS. Before executing (after ' +
    'the script is parsed) we set breakpoints in the asm.js code.');

function testFunction() {
  function generateAsmJs(stdlib, foreign, heap) {
    'use asm';
    var debugger_fun = foreign.call_debugger;
    function callDebugger() {
      debugger_fun();
    }
    function redirectFun() {
      callDebugger();
    }
    return redirectFun;
  }

  function call_debugger() {
    debugger;
  }

  %OptimizeFunctionOnNextCall(generateAsmJs);
  var fun = generateAsmJs(this, {'call_debugger': call_debugger}, undefined);
  fun();
}

Protocol.Debugger.onPaused(handleDebuggerPaused);
Protocol.Debugger.onScriptParsed(handleScriptParsed);

function printResultAndContinue(next, message) {
  if (message.result && message.result.exceptionDetails)
    InspectorTest.logMessage(message.result.exceptionDetails);
  else if (message.error)
    InspectorTest.logMessage(message.error);
  else if (message.result && message.result.type !== undefined)
    InspectorTest.logMessage(message.result);
  next();
}

InspectorTest.runTestSuite([
  function enableDebugger(next) {
    Protocol.Debugger.enable().then(next);
  },

  function addScript(next) {
    afterScriptParsedCallback = next;
    contextGroup.addScript(testFunction.toString());
  },

  function runTestFunction(next) {
    Protocol.Runtime.evaluate({'expression': 'testFunction()'})
        .then(printResultAndContinue.bind(null, next));
  },

  function finished(next) {
    InspectorTest.log('Finished TestSuite.');
    next();
  },
]);

function locationToString(callFrame) {
  var res = {functionName: callFrame.functionName};
  for (var attr in callFrame.functionLocation) {
    if (attr == 'scriptId') continue;
    res['function_' + attr] = callFrame.functionLocation[attr];
  }
  for (var attr in callFrame.location) {
    if (attr == 'scriptId') continue;
    res[attr] = callFrame.location[attr];
  }
  return JSON.stringify(res);
}

function logStackTrace(messageObject) {
  var frames = messageObject.params.callFrames;
  for (var i = 0; i < frames.length; ++i) {
    InspectorTest.log('  - [' + i + '] ' + locationToString(frames[i]));
  }
}

var numPaused = 0;

function handleDebuggerPaused(messageObject)
{
  ++numPaused;
  InspectorTest.log('Paused #' + numPaused);
  logStackTrace(messageObject);
  Protocol.Debugger.resume();
}

var numScripts = 0;

function handleScriptParsed(messageObject)
{
  var scriptId = messageObject.params.scriptId;
  ++numScripts;
  InspectorTest.log('Script nr ' + numScripts + ' parsed!');
  if (numScripts > 1) return;

  var startLine = messageObject.params.startLine + 3;
  var endLine = messageObject.params.endLine;
  InspectorTest.log('First script; assuming testFunction.');
  InspectorTest.log(
      'Flooding script with breakpoints for the lines ' + startLine + ' to ' +
      endLine + '...');
  var currentLine = startLine;
  function setNextBreakpoint(message) {
    if (message) InspectorTest.logMessage('error: ' + message.error);
    if (currentLine == endLine) {
      afterScriptParsedCallback();
      return;
    }
    var thisLine = currentLine;
    currentLine += 1;
    InspectorTest.log('Setting breakpoint on line ' + thisLine);
    Protocol.Debugger
        .setBreakpoint(
            {'location': {'scriptId': scriptId, 'lineNumber': thisLine}})
        .then(setNextBreakpoint);
  }
  setNextBreakpoint();
}
