// 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: --expose-wasm

let {session, contextGroup, Protocol} = InspectorTest.start('Tests breakable locations in wasm');

utils.load('test/mjsunit/wasm/wasm-module-builder.js');

var builder = new WasmModuleBuilder();

// clang-format off
var func_idx = builder.addFunction('helper', kSig_v_v)
    .addLocals({i32_count: 1})
    .addBody([
        kExprNop,
        kExprI32Const, 12,
        kExprSetLocal, 0,
    ]).index;

builder.addFunction('main', kSig_v_i)
    .addBody([
        kExprGetLocal, 0,
        kExprIf, kWasmStmt,
          kExprBlock, kWasmStmt,
            kExprCallFunction, func_idx,
          kExprEnd,
        kExprEnd
    ]).exportAs('main');
// clang-format on

var module_bytes = builder.toArray();

function testFunction(bytes) {
  var buffer = new ArrayBuffer(bytes.length);
  var view = new Uint8Array(buffer);
  for (var i = 0; i < bytes.length; i++) {
    view[i] = bytes[i] | 0;
  }

  var module = new WebAssembly.Module(buffer);
  // Set global variable.
  instance = new WebAssembly.Instance(module);
}

var evalWithUrl = (code, url) => Protocol.Runtime.evaluate(
    {'expression': code + '\n//# sourceURL=v8://test/' + url});

var setupCode = testFunction.toString() + ';\nvar module_bytes = ' +
    JSON.stringify(module_bytes) + ';\nvar instance;';

Protocol.Debugger.enable();
Protocol.Debugger.onScriptParsed(handleScriptParsed);
InspectorTest.log('Running testFunction...');
evalWithUrl(setupCode, 'setup')
    .then(() => evalWithUrl('testFunction(module_bytes)', 'runTestFunction'))
    .then(getBreakableLocationsForAllWasmScripts)
    .then(setAllBreakableLocations)
    .then(() => InspectorTest.log('Running wasm code...'))
    .then(() => (evalWithUrl('instance.exports.main(1)', 'runWasm'), 0))
    .then(waitForAllPauses)
    .then(() => InspectorTest.log('Finished!'))
    .then(InspectorTest.completeTest);

var allBreakableLocations = [];

var urls = {};
var numScripts = 0;
var wasmScripts = [];
function handleScriptParsed(messageObject) {
  var scriptId = messageObject.params.scriptId;
  var url = messageObject.params.url;
  urls[scriptId] = url;
  InspectorTest.log('Script nr ' + numScripts + ' parsed. URL: ' + url);
  ++numScripts;

  if (url.startsWith('wasm://')) {
    InspectorTest.log('This is a wasm script (nr ' + wasmScripts.length + ').');
    wasmScripts.push(scriptId);
  }
}

function printFailure(message) {
  if (!message.result) {
    InspectorTest.logMessage(message);
  }
  return message;
}

function printBreakableLocations(message, expectedScriptId, source) {
  var lines = source.split('\n');
  var locations = message.result.locations;
  InspectorTest.log(locations.length + ' breakable location(s):');
  for (var i = 0; i < locations.length; ++i) {
    if (locations[i].scriptId != expectedScriptId) {
      InspectorTest.log(
          'SCRIPT ID MISMATCH!! ' + locations[i].scriptId + ' != ' +
          expectedScriptId);
    }
    var line = '<illegal line number>';
    if (locations[i].lineNumber < lines.length) {
      line = lines[locations[i].lineNumber];
      if (locations[i].columnNumber < line.length) {
        line = line.substr(0, locations[i].columnNumber) + '>' +
            line.substr(locations[i].columnNumber);
      }
    }
    InspectorTest.log(
        '[' + i + '] ' + locations[i].lineNumber + ':' +
        locations[i].columnNumber + ' || ' + line);
  }
}

function checkGetBreakableLocations(wasmScriptNr) {
  InspectorTest.log(
      'Requesting all breakable locations in wasm script ' + wasmScriptNr);
  var scriptId = wasmScripts[wasmScriptNr];
  var source;
  return Protocol.Debugger.getScriptSource({scriptId: scriptId})
      .then(msg => source = msg.result.scriptSource)
      .then(
          () => Protocol.Debugger.getPossibleBreakpoints(
              {start: {lineNumber: 0, columnNumber: 0, scriptId: scriptId}}))
      .then(printFailure)
      .then(msg => (allBreakableLocations.push(...msg.result.locations), msg))
      .then(msg => printBreakableLocations(msg, scriptId, source))
      .then(
          () => InspectorTest.log(
              'Requesting breakable locations in lines [0,3)'))
      .then(() => Protocol.Debugger.getPossibleBreakpoints({
        start: {lineNumber: 0, columnNumber: 0, scriptId: scriptId},
        end: {lineNumber: 3, columnNumber: 0, scriptId: scriptId}
      }))
      .then(printFailure)
      .then(msg => printBreakableLocations(msg, scriptId, source))
      .then(
          () => InspectorTest.log(
              'Requesting breakable locations in lines [4,6)'))
      .then(() => Protocol.Debugger.getPossibleBreakpoints({
        start: {lineNumber: 4, columnNumber: 0, scriptId: scriptId},
        end: {lineNumber: 6, columnNumber: 0, scriptId: scriptId}
      }))
      .then(printFailure)
      .then(msg => printBreakableLocations(msg, scriptId, source));
}

function getBreakableLocationsForAllWasmScripts() {
  InspectorTest.log('Querying breakable locations for all wasm scripts now...');
  var promise = Promise.resolve();
  for (var wasmScriptNr = 0; wasmScriptNr < wasmScripts.length;
       ++wasmScriptNr) {
    promise = promise.then(checkGetBreakableLocations.bind(null, wasmScriptNr));
  }
  return promise;
}

function locationMatches(loc1, loc2) {
  return loc1.scriptId == loc2.scriptId && loc1.lineNumber == loc2.lineNumber &&
      loc1.columnNumber == loc2.columnNumber;
}

function locationStr(loc) {
  return urls[loc.scriptId] + ':' + loc.lineNumber + ':' + loc.columnNumber;
}

function setBreakpoint(loc) {
  InspectorTest.log('Setting at ' + locationStr(loc));
  function check(msg) {
    if (locationMatches(loc, msg.result.actualLocation)) {
      InspectorTest.log("Success!");
    } else {
      InspectorTest.log("Mismatch!");
      InspectorTest.logMessage(msg);
    }
  }
  return Protocol.Debugger.setBreakpoint({'location': loc})
      .then(printFailure)
      .then(check);
}

function setAllBreakableLocations() {
  InspectorTest.log('Setting a breakpoint on each breakable location...');
  var promise = Promise.resolve();
  for (var loc of allBreakableLocations) {
    promise = promise.then(setBreakpoint.bind(null, loc));
  }
  return promise;
}

function removePausedLocation(msg) {
  var topLocation = msg.params.callFrames[0].location;
  InspectorTest.log('Stopped at ' + locationStr(topLocation));
  for (var i = 0; i < allBreakableLocations.length; ++i) {
    if (locationMatches(topLocation, allBreakableLocations[i])) {
      allBreakableLocations.splice(i, 1);
      --i;
    }
  }
}

function waitForAllPauses() {
  InspectorTest.log('Missing breakpoints: ' + allBreakableLocations.length);
  if (allBreakableLocations.length == 0) return;
  return Protocol.Debugger.oncePaused()
      .then(removePausedLocation)
      .then(Protocol.Debugger.resume())
      .then(waitForAllPauses);
}
