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

#include "src/runtime/runtime-utils.h"

#include "src/arguments.h"
#include "src/debug/debug.h"
#include "src/debug/debug-frames.h"
#include "src/debug/liveedit.h"
#include "src/frames-inl.h"
#include "src/isolate-inl.h"
#include "src/runtime/runtime.h"

namespace v8 {
namespace internal {

// For a script finds all SharedFunctionInfo's in the heap that points
// to this script. Returns JSArray of SharedFunctionInfo wrapped
// in OpaqueReferences.
RUNTIME_FUNCTION(Runtime_LiveEditFindSharedFunctionInfosForScript) {
  HandleScope scope(isolate);
  CHECK(isolate->debug()->live_edit_enabled());
  DCHECK_EQ(1, args.length());
  CONVERT_ARG_CHECKED(JSValue, script_value, 0);

  CHECK(script_value->value()->IsScript());
  Handle<Script> script = Handle<Script>(Script::cast(script_value->value()));

  std::vector<Handle<SharedFunctionInfo>> found;
  Heap* heap = isolate->heap();
  {
    HeapIterator iterator(heap);
    HeapObject* heap_obj;
    while ((heap_obj = iterator.next()) != nullptr) {
      if (!heap_obj->IsSharedFunctionInfo()) continue;
      SharedFunctionInfo* shared = SharedFunctionInfo::cast(heap_obj);
      if (shared->script() != *script) continue;
      found.push_back(Handle<SharedFunctionInfo>(shared));
    }
  }

  int found_size = static_cast<int>(found.size());
  Handle<FixedArray> result = isolate->factory()->NewFixedArray(found_size);
  for (int i = 0; i < found_size; ++i) {
    Handle<SharedFunctionInfo> shared = found[i];
    SharedInfoWrapper info_wrapper = SharedInfoWrapper::Create(isolate);
    Handle<String> name(shared->name(), isolate);
    info_wrapper.SetProperties(name, shared->start_position(),
                               shared->end_position(), shared);
    result->set(i, *info_wrapper.GetJSArray());
  }
  return *isolate->factory()->NewJSArrayWithElements(result);
}


// For a script calculates compilation information about all its functions.
// The script source is explicitly specified by the second argument.
// The source of the actual script is not used, however it is important that
// all generated code keeps references to this particular instance of script.
// Returns a JSArray of compilation infos. The array is ordered so that
// each function with all its descendant is always stored in a continues range
// with the function itself going first. The root function is a script function.
RUNTIME_FUNCTION(Runtime_LiveEditGatherCompileInfo) {
  HandleScope scope(isolate);
  CHECK(isolate->debug()->live_edit_enabled());
  DCHECK_EQ(2, args.length());
  CONVERT_ARG_CHECKED(JSValue, script, 0);
  CONVERT_ARG_HANDLE_CHECKED(String, source, 1);

  CHECK(script->value()->IsScript());
  Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));

  RETURN_RESULT_OR_FAILURE(isolate,
                           LiveEdit::GatherCompileInfo(script_handle, source));
}


// Changes the source of the script to a new_source.
// If old_script_name is provided (i.e. is a String), also creates a copy of
// the script with its original source and sends notification to debugger.
RUNTIME_FUNCTION(Runtime_LiveEditReplaceScript) {
  HandleScope scope(isolate);
  CHECK(isolate->debug()->live_edit_enabled());
  DCHECK_EQ(3, args.length());
  CONVERT_ARG_CHECKED(JSValue, original_script_value, 0);
  CONVERT_ARG_HANDLE_CHECKED(String, new_source, 1);
  CONVERT_ARG_HANDLE_CHECKED(Object, old_script_name, 2);

  CHECK(original_script_value->value()->IsScript());
  Handle<Script> original_script(Script::cast(original_script_value->value()));

  Handle<Object> old_script = LiveEdit::ChangeScriptSource(
      original_script, new_source, old_script_name);

  if (old_script->IsScript()) {
    Handle<Script> script_handle = Handle<Script>::cast(old_script);
    return *Script::GetWrapper(script_handle);
  } else {
    return isolate->heap()->null_value();
  }
}

// Recreate the shared function infos array after changing the IDs of all
// SharedFunctionInfos.
RUNTIME_FUNCTION(Runtime_LiveEditFixupScript) {
  HandleScope scope(isolate);
  CHECK(isolate->debug()->live_edit_enabled());
  DCHECK_EQ(args.length(), 2);
  CONVERT_ARG_CHECKED(JSValue, script_value, 0);
  CONVERT_INT32_ARG_CHECKED(max_function_literal_id, 1);

  CHECK(script_value->value()->IsScript());
  Handle<Script> script(Script::cast(script_value->value()));

  LiveEdit::FixupScript(script, max_function_literal_id);
  return isolate->heap()->undefined_value();
}

RUNTIME_FUNCTION(Runtime_LiveEditFunctionSourceUpdated) {
  HandleScope scope(isolate);
  CHECK(isolate->debug()->live_edit_enabled());
  DCHECK_EQ(args.length(), 2);
  CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_info, 0);
  CONVERT_INT32_ARG_CHECKED(new_function_literal_id, 1);
  CHECK(SharedInfoWrapper::IsInstance(shared_info));

  LiveEdit::FunctionSourceUpdated(shared_info, new_function_literal_id);
  return isolate->heap()->undefined_value();
}


// Replaces code of SharedFunctionInfo with a new one.
RUNTIME_FUNCTION(Runtime_LiveEditReplaceFunctionCode) {
  HandleScope scope(isolate);
  CHECK(isolate->debug()->live_edit_enabled());
  DCHECK_EQ(2, args.length());
  CONVERT_ARG_HANDLE_CHECKED(JSArray, new_compile_info, 0);
  CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_info, 1);
  CHECK(SharedInfoWrapper::IsInstance(shared_info));

  LiveEdit::ReplaceFunctionCode(new_compile_info, shared_info);
  return isolate->heap()->undefined_value();
}


// Connects SharedFunctionInfo to another script.
RUNTIME_FUNCTION(Runtime_LiveEditFunctionSetScript) {
  HandleScope scope(isolate);
  CHECK(isolate->debug()->live_edit_enabled());
  DCHECK_EQ(2, args.length());
  CONVERT_ARG_HANDLE_CHECKED(Object, function_object, 0);
  CONVERT_ARG_HANDLE_CHECKED(Object, script_object, 1);

  if (function_object->IsJSValue()) {
    Handle<JSValue> function_wrapper = Handle<JSValue>::cast(function_object);
    if (script_object->IsJSValue()) {
      CHECK(JSValue::cast(*script_object)->value()->IsScript());
      Script* script = Script::cast(JSValue::cast(*script_object)->value());
      script_object = Handle<Object>(script, isolate);
    }
    CHECK(function_wrapper->value()->IsSharedFunctionInfo());
    LiveEdit::SetFunctionScript(function_wrapper, script_object);
  } else {
    // Just ignore this. We may not have a SharedFunctionInfo for some functions
    // and we check it in this function.
  }

  return isolate->heap()->undefined_value();
}


// In a code of a parent function replaces original function as embedded object
// with a substitution one.
RUNTIME_FUNCTION(Runtime_LiveEditReplaceRefToNestedFunction) {
  HandleScope scope(isolate);
  CHECK(isolate->debug()->live_edit_enabled());
  DCHECK_EQ(3, args.length());

  CONVERT_ARG_HANDLE_CHECKED(JSValue, parent_wrapper, 0);
  CONVERT_ARG_HANDLE_CHECKED(JSValue, orig_wrapper, 1);
  CONVERT_ARG_HANDLE_CHECKED(JSValue, subst_wrapper, 2);
  CHECK(parent_wrapper->value()->IsSharedFunctionInfo());
  CHECK(orig_wrapper->value()->IsSharedFunctionInfo());
  CHECK(subst_wrapper->value()->IsSharedFunctionInfo());

  LiveEdit::ReplaceRefToNestedFunction(parent_wrapper, orig_wrapper,
                                       subst_wrapper);
  return isolate->heap()->undefined_value();
}


// Updates positions of a shared function info (first parameter) according
// to script source change. Text change is described in second parameter as
// array of groups of 3 numbers:
// (change_begin, change_end, change_end_new_position).
// Each group describes a change in text; groups are sorted by change_begin.
RUNTIME_FUNCTION(Runtime_LiveEditPatchFunctionPositions) {
  HandleScope scope(isolate);
  CHECK(isolate->debug()->live_edit_enabled());
  DCHECK_EQ(2, args.length());
  CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_array, 0);
  CONVERT_ARG_HANDLE_CHECKED(JSArray, position_change_array, 1);
  CHECK(SharedInfoWrapper::IsInstance(shared_array));

  LiveEdit::PatchFunctionPositions(shared_array, position_change_array);
  return isolate->heap()->undefined_value();
}


// For array of SharedFunctionInfo's (each wrapped in JSValue)
// checks that none of them have activations on stacks (of any thread).
// Returns array of the same length with corresponding results of
// LiveEdit::FunctionPatchabilityStatus type.
RUNTIME_FUNCTION(Runtime_LiveEditCheckAndDropActivations) {
  HandleScope scope(isolate);
  CHECK(isolate->debug()->live_edit_enabled());
  DCHECK_EQ(3, args.length());
  CONVERT_ARG_HANDLE_CHECKED(JSArray, old_shared_array, 0);
  CONVERT_ARG_HANDLE_CHECKED(JSArray, new_shared_array, 1);
  CONVERT_BOOLEAN_ARG_CHECKED(do_drop, 2);
  USE(new_shared_array);
  CHECK(old_shared_array->length()->IsSmi());
  CHECK(new_shared_array->length() == old_shared_array->length());
  CHECK(old_shared_array->HasFastElements());
  CHECK(new_shared_array->HasFastElements());
  int array_length = Smi::ToInt(old_shared_array->length());
  for (int i = 0; i < array_length; i++) {
    Handle<Object> old_element;
    Handle<Object> new_element;
    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
        isolate, old_element,
        JSReceiver::GetElement(isolate, old_shared_array, i));
    CHECK(old_element->IsJSValue() &&
          Handle<JSValue>::cast(old_element)->value()->IsSharedFunctionInfo());
    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
        isolate, new_element,
        JSReceiver::GetElement(isolate, new_shared_array, i));
    CHECK(
        new_element->IsUndefined(isolate) ||
        (new_element->IsJSValue() &&
         Handle<JSValue>::cast(new_element)->value()->IsSharedFunctionInfo()));
  }

  return *LiveEdit::CheckAndDropActivations(old_shared_array, new_shared_array,
                                            do_drop);
}


// Compares 2 strings line-by-line, then token-wise and returns diff in form
// of JSArray of triplets (pos1, pos1_end, pos2_end) describing list
// of diff chunks.
RUNTIME_FUNCTION(Runtime_LiveEditCompareStrings) {
  HandleScope scope(isolate);
  CHECK(isolate->debug()->live_edit_enabled());
  DCHECK_EQ(2, args.length());
  CONVERT_ARG_HANDLE_CHECKED(String, s1, 0);
  CONVERT_ARG_HANDLE_CHECKED(String, s2, 1);

  Handle<JSArray> result = LiveEdit::CompareStrings(s1, s2);
  uint32_t array_length = 0;
  CHECK(result->length()->ToArrayLength(&array_length));
  if (array_length > 0) {
    isolate->debug()->feature_tracker()->Track(DebugFeatureTracker::kLiveEdit);
  }

  return *result;
}


// Restarts a call frame and completely drops all frames above.
// Returns true if successful. Otherwise returns undefined or an error message.
RUNTIME_FUNCTION(Runtime_LiveEditRestartFrame) {
  HandleScope scope(isolate);
  CHECK(isolate->debug()->live_edit_enabled());
  DCHECK_EQ(2, args.length());
  CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
  CHECK(isolate->debug()->CheckExecutionState(break_id));

  CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
  Heap* heap = isolate->heap();

  // Find the relevant frame with the requested index.
  StackFrame::Id id = isolate->debug()->break_frame_id();
  if (id == StackFrame::NO_ID) {
    // If there are no JavaScript stack frames return undefined.
    return heap->undefined_value();
  }

  StackTraceFrameIterator it(isolate, id);
  int inlined_jsframe_index =
      DebugFrameHelper::FindIndexedNonNativeFrame(&it, index);
  // Liveedit is not supported on Wasm.
  if (inlined_jsframe_index == -1 || it.is_wasm()) {
    return heap->undefined_value();
  }
  // We don't really care what the inlined frame index is, since we are
  // throwing away the entire frame anyways.
  const char* error_message = LiveEdit::RestartFrame(it.javascript_frame());
  if (error_message) {
    return *(isolate->factory()->InternalizeUtf8String(error_message));
  }
  return heap->true_value();
}
}  // namespace internal
}  // namespace v8
