// Copyright 2018 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.

utils.load('test/inspector/wasm-inspector-test.js');

let {session, contextGroup, Protocol} =
    InspectorTest.start('Tests stepping through wasm scripts with source maps');
session.setupScriptMap();

var builder = new WasmModuleBuilder();

var func_a_idx =
    builder.addFunction('wasm_A', kSig_v_v).addBody([kExprNop, kExprNop]).index;

// wasm_B calls wasm_A <param0> times.
builder.addFunction('wasm_B', kSig_v_i)
    .addBody([
      // clang-format off
      kExprLoop, kWasmStmt,               // while
        kExprLocalGet, 0,                 // -
        kExprIf, kWasmStmt,               // if <param0> != 0
          kExprLocalGet, 0,               // -
          kExprI32Const, 1,               // -
          kExprI32Sub,                    // -
          kExprLocalSet, 0,               // decrease <param0>
          kExprCallFunction, func_a_idx,  // -
          kExprBr, 1,                     // continue
          kExprEnd,                       // -
        kExprEnd,                         // break
      // clang-format on
    ])
    .exportAs('main');

builder.addCustomSection('sourceMappingURL', [3, 97, 98, 99]);

var module_bytes = builder.toArray();

(async function test() {
  for (const action of ['stepInto', 'stepOver', 'stepOut', 'resume'])
    InspectorTest.logProtocolCommandCalls('Debugger.' + action);

  await Protocol.Debugger.enable();
  WasmInspectorTest.instantiate(module_bytes);
  const [, {params: wasmScript}] = await Protocol.Debugger.onceScriptParsed(2);

  InspectorTest.log('Got wasm script: ' + wasmScript.url);
  InspectorTest.log('Script sourceMapURL: ' + wasmScript.sourceMapURL);
  InspectorTest.log('Requesting source for ' + wasmScript.url + '...');
  const msg =
      await Protocol.Debugger.getScriptSource({scriptId: wasmScript.scriptId});
  InspectorTest.log(`Source retrieved without error: ${!msg.error}`);
  InspectorTest.log(
      `Setting breakpoint on offset 54 (on the setlocal before the call), url ${wasmScript.url}`);
  const {result: {actualLocation}} = await Protocol.Debugger.setBreakpoint({
    location:{scriptId: wasmScript.scriptId, lineNumber: 0, columnNumber: 54}});
  InspectorTest.logMessage(actualLocation);
  Protocol.Runtime.evaluate({expression: 'instance.exports.main(4)'});
  await waitForPauseAndStep('stepInto');  // == stepOver, to call instruction
  await waitForPauseAndStep('stepInto');  // into call to wasm_A
  await waitForPauseAndStep('stepOver');  // over first nop
  await waitForPauseAndStep('stepOut');   // out of wasm_A
  await waitForPauseAndStep('stepOut');  // out of wasm_B, stop on breakpoint again
  await waitForPauseAndStep('stepOver');  // to call
  await waitForPauseAndStep('stepOver');  // over call
  await waitForPauseAndStep('resume');  // to next breakpoint (third iteration)
  await waitForPauseAndStep('stepInto');  // to call
  await waitForPauseAndStep('stepInto');  // into wasm_A
  await waitForPauseAndStep('stepOut');   // out to wasm_B
  // Now step 8 times, until we are in wasm_A again.
  for (let i = 0; i < 8; ++i) await waitForPauseAndStep('stepInto');
  // 3 more times, back to wasm_B.
  for (let i = 0; i < 3; ++i) await waitForPauseAndStep('stepInto');
  // then just resume.
  await waitForPauseAndStep('resume');
  InspectorTest.log('exports.main returned!');
  InspectorTest.log('Finished!');
  InspectorTest.completeTest();
})();

async function waitForPauseAndStep(stepAction) {
  const {params: {callFrames}} = await Protocol.Debugger.oncePaused();
  await session.logSourceLocation(callFrames[0].location);
  for (var frame of callFrames) {
    const functionName = frame.functionName || '(anonymous)';
    const lineNumber = frame.location.lineNumber;
    const columnNumber = frame.location.columnNumber;
    InspectorTest.log(`at ${functionName} (${lineNumber}:${columnNumber}):`);
    for (var scope of frame.scopeChain) {
      InspectorTest.logObject(' - scope (' + scope.type + '):');
      if (scope.type === 'global' || scope.type === 'module') {
        InspectorTest.logObject('   -- skipped');
      } else {
        const {result: {result: {value}}} =
            await Protocol.Runtime.callFunctionOn({
              objectId: scope.object.objectId,
              functionDeclaration: 'function() { return this; }',
              returnByValue: true
            });

        InspectorTest.log(`   ${JSON.stringify(value)}`);
      }
    }
  }
  Protocol.Debugger[stepAction]();
}
