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

#include "src/builtins/builtins-utils.h"
#include "src/builtins/builtins.h"
#include "src/code-factory.h"
#include "src/code-stub-assembler.h"
#include "src/compiler.h"
#include "src/uri.h"

namespace v8 {
namespace internal {

// ES6 section 18.2.6.2 decodeURI (encodedURI)
BUILTIN(GlobalDecodeURI) {
  HandleScope scope(isolate);
  Handle<String> encoded_uri;
  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
      isolate, encoded_uri,
      Object::ToString(isolate, args.atOrUndefined(isolate, 1)));

  RETURN_RESULT_OR_FAILURE(isolate, Uri::DecodeUri(isolate, encoded_uri));
}

// ES6 section 18.2.6.3 decodeURIComponent (encodedURIComponent)
BUILTIN(GlobalDecodeURIComponent) {
  HandleScope scope(isolate);
  Handle<String> encoded_uri_component;
  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
      isolate, encoded_uri_component,
      Object::ToString(isolate, args.atOrUndefined(isolate, 1)));

  RETURN_RESULT_OR_FAILURE(
      isolate, Uri::DecodeUriComponent(isolate, encoded_uri_component));
}

// ES6 section 18.2.6.4 encodeURI (uri)
BUILTIN(GlobalEncodeURI) {
  HandleScope scope(isolate);
  Handle<String> uri;
  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
      isolate, uri, Object::ToString(isolate, args.atOrUndefined(isolate, 1)));

  RETURN_RESULT_OR_FAILURE(isolate, Uri::EncodeUri(isolate, uri));
}

// ES6 section 18.2.6.5 encodeURIComponenet (uriComponent)
BUILTIN(GlobalEncodeURIComponent) {
  HandleScope scope(isolate);
  Handle<String> uri_component;
  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
      isolate, uri_component,
      Object::ToString(isolate, args.atOrUndefined(isolate, 1)));

  RETURN_RESULT_OR_FAILURE(isolate,
                           Uri::EncodeUriComponent(isolate, uri_component));
}

// ES6 section B.2.1.1 escape (string)
BUILTIN(GlobalEscape) {
  HandleScope scope(isolate);
  Handle<String> string;
  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
      isolate, string,
      Object::ToString(isolate, args.atOrUndefined(isolate, 1)));

  RETURN_RESULT_OR_FAILURE(isolate, Uri::Escape(isolate, string));
}

// ES6 section B.2.1.2 unescape (string)
BUILTIN(GlobalUnescape) {
  HandleScope scope(isolate);
  Handle<String> string;
  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
      isolate, string,
      Object::ToString(isolate, args.atOrUndefined(isolate, 1)));

  RETURN_RESULT_OR_FAILURE(isolate, Uri::Unescape(isolate, string));
}

// ES6 section 18.2.1 eval (x)
BUILTIN(GlobalEval) {
  HandleScope scope(isolate);
  Handle<Object> x = args.atOrUndefined(isolate, 1);
  Handle<JSFunction> target = args.target();
  Handle<JSObject> target_global_proxy(target->global_proxy(), isolate);
  if (!x->IsString()) return *x;
  if (!Builtins::AllowDynamicFunction(isolate, target, target_global_proxy)) {
    isolate->CountUsage(v8::Isolate::kFunctionConstructorReturnedUndefined);
    return isolate->heap()->undefined_value();
  }
  Handle<JSFunction> function;
  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
      isolate, function,
      Compiler::GetFunctionFromString(handle(target->native_context(), isolate),
                                      Handle<String>::cast(x),
                                      NO_PARSE_RESTRICTION, kNoSourcePosition));
  RETURN_RESULT_OR_FAILURE(
      isolate,
      Execution::Call(isolate, function, target_global_proxy, 0, nullptr));
}

// ES6 section 18.2.2 isFinite ( number )
void Builtins::Generate_GlobalIsFinite(compiler::CodeAssemblerState* state) {
  typedef CodeStubAssembler::Label Label;
  typedef compiler::Node Node;
  typedef CodeStubAssembler::Variable Variable;
  CodeStubAssembler assembler(state);

  Node* context = assembler.Parameter(4);

  Label return_true(&assembler), return_false(&assembler);

  // We might need to loop once for ToNumber conversion.
  Variable var_num(&assembler, MachineRepresentation::kTagged);
  Label loop(&assembler, &var_num);
  var_num.Bind(assembler.Parameter(1));
  assembler.Goto(&loop);
  assembler.Bind(&loop);
  {
    // Load the current {num} value.
    Node* num = var_num.value();

    // Check if {num} is a Smi or a HeapObject.
    assembler.GotoIf(assembler.TaggedIsSmi(num), &return_true);

    // Check if {num} is a HeapNumber.
    Label if_numisheapnumber(&assembler),
        if_numisnotheapnumber(&assembler, Label::kDeferred);
    assembler.Branch(assembler.IsHeapNumberMap(assembler.LoadMap(num)),
                     &if_numisheapnumber, &if_numisnotheapnumber);

    assembler.Bind(&if_numisheapnumber);
    {
      // Check if {num} contains a finite, non-NaN value.
      Node* num_value = assembler.LoadHeapNumberValue(num);
      assembler.BranchIfFloat64IsNaN(assembler.Float64Sub(num_value, num_value),
                                     &return_false, &return_true);
    }

    assembler.Bind(&if_numisnotheapnumber);
    {
      // Need to convert {num} to a Number first.
      Callable callable = CodeFactory::NonNumberToNumber(assembler.isolate());
      var_num.Bind(assembler.CallStub(callable, context, num));
      assembler.Goto(&loop);
    }
  }

  assembler.Bind(&return_true);
  assembler.Return(assembler.BooleanConstant(true));

  assembler.Bind(&return_false);
  assembler.Return(assembler.BooleanConstant(false));
}

// ES6 section 18.2.3 isNaN ( number )
void Builtins::Generate_GlobalIsNaN(compiler::CodeAssemblerState* state) {
  typedef CodeStubAssembler::Label Label;
  typedef compiler::Node Node;
  typedef CodeStubAssembler::Variable Variable;
  CodeStubAssembler assembler(state);

  Node* context = assembler.Parameter(4);

  Label return_true(&assembler), return_false(&assembler);

  // We might need to loop once for ToNumber conversion.
  Variable var_num(&assembler, MachineRepresentation::kTagged);
  Label loop(&assembler, &var_num);
  var_num.Bind(assembler.Parameter(1));
  assembler.Goto(&loop);
  assembler.Bind(&loop);
  {
    // Load the current {num} value.
    Node* num = var_num.value();

    // Check if {num} is a Smi or a HeapObject.
    assembler.GotoIf(assembler.TaggedIsSmi(num), &return_false);

    // Check if {num} is a HeapNumber.
    Label if_numisheapnumber(&assembler),
        if_numisnotheapnumber(&assembler, Label::kDeferred);
    assembler.Branch(assembler.IsHeapNumberMap(assembler.LoadMap(num)),
                     &if_numisheapnumber, &if_numisnotheapnumber);

    assembler.Bind(&if_numisheapnumber);
    {
      // Check if {num} contains a NaN.
      Node* num_value = assembler.LoadHeapNumberValue(num);
      assembler.BranchIfFloat64IsNaN(num_value, &return_true, &return_false);
    }

    assembler.Bind(&if_numisnotheapnumber);
    {
      // Need to convert {num} to a Number first.
      Callable callable = CodeFactory::NonNumberToNumber(assembler.isolate());
      var_num.Bind(assembler.CallStub(callable, context, num));
      assembler.Goto(&loop);
    }
  }

  assembler.Bind(&return_true);
  assembler.Return(assembler.BooleanConstant(true));

  assembler.Bind(&return_false);
  assembler.Return(assembler.BooleanConstant(false));
}

}  // namespace internal
}  // namespace v8
