// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Implementation of functions that are shared between ReadableStream and
// WritableStream.

#include "third_party/blink/renderer/core/streams/miscellaneous_operations.h"

#include <math.h>

#include "base/optional.h"
#include "third_party/blink/renderer/core/streams/stream_algorithms.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h"
#include "third_party/blink/renderer/platform/bindings/v8_binding.h"
#include "third_party/blink/renderer/platform/heap/visitor.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"

namespace blink {

namespace {

// ResolveMethod implements part of CreateAlgorithmFromUnderlyingMethod and
// CallOrNoop1.
v8::MaybeLocal<v8::Value> ResolveMethod(ScriptState* script_state,
                                        v8::Local<v8::Object> object,
                                        const char* method_name,
                                        const char* name_for_error,
                                        ExceptionState& exception_state) {
  auto* isolate = script_state->GetIsolate();
  v8::TryCatch try_catch(isolate);

  // Algorithm steps from CreateAlgorithmFromUnderlyingMethod in the standard.
  // https://streams.spec.whatwg.org/#create-algorithm-from-underlying-method
  // 5. Let method be ? GetV(underlyingObject, methodName).
  auto method_maybe = object->Get(script_state->GetContext(),
                                  V8AtomicString(isolate, method_name));
  v8::Local<v8::Value> method;
  if (!method_maybe.ToLocal(&method)) {
    exception_state.RethrowV8Exception(try_catch.Exception());
    return v8::MaybeLocal<v8::Value>();
  }

  // 6. If method is not undefined,
  //    a. If ! IsCallable(method) is false, throw a TypeError exception.
  if (!method->IsFunction() && !method->IsUndefined()) {
    exception_state.ThrowTypeError(String(name_for_error) +
                                   " must be a function or undefined");
    return v8::MaybeLocal<v8::Value>();
  }

  return method;
}

// PromiseRejectInternal() implements Promise.reject(_r_) from the ECMASCRIPT
// standard, https://tc39.github.io/ecma262/#sec-promise.reject.
// The |recursion_depth| argument is used to prevent infinite recursion in the
// case that we can't create a promise.
v8::Local<v8::Promise> PromiseRejectInternal(ScriptState* script_state,
                                             v8::Local<v8::Value> value,
                                             int recursion_depth) {
  auto context = script_state->GetContext();
  v8::TryCatch trycatch(script_state->GetIsolate());
  // TODO(ricea): Can this fail for reasons other than memory exhaustion? Can we
  // recover if it does?
  auto resolver = v8::Promise::Resolver::New(context).ToLocalChecked();
  if (resolver->Reject(context, value).IsNothing()) {
    // Assume that the exception can be successfully used to create a Promise.
    // TODO(ricea): Can the body of this if statement actually be reached?
    if (recursion_depth >= 2) {
      LOG(FATAL) << "Recursion depth exceeded in PromiseRejectInternal";
    }
    return PromiseRejectInternal(script_state, trycatch.Exception(),
                                 recursion_depth + 1);
  }
  return resolver->GetPromise();
}

class DefaultSizeAlgorithm final : public StrategySizeAlgorithm {
 public:
  base::Optional<double> Run(ScriptState*,
                             v8::Local<v8::Value>,
                             ExceptionState&) override {
    return 1;
  }
};

class JavaScriptSizeAlgorithm final : public StrategySizeAlgorithm {
 public:
  JavaScriptSizeAlgorithm(v8::Isolate* isolate, v8::Local<v8::Function> size)
      : function_(isolate, size) {}

  base::Optional<double> Run(ScriptState* script_state,
                             v8::Local<v8::Value> chunk,
                             ExceptionState& exception_state) override {
    auto* isolate = script_state->GetIsolate();
    auto context = script_state->GetContext();
    v8::TryCatch trycatch(isolate);
    v8::Local<v8::Value> argv[] = {chunk};

    // https://streams.spec.whatwg.org/#make-size-algorithm-from-size-function
    // 3.a. Return ? Call(size, undefined, « chunk »).
    v8::MaybeLocal<v8::Value> result_maybe = function_.NewLocal(isolate)->Call(
        context, v8::Undefined(isolate), 1, argv);
    v8::Local<v8::Value> result;
    if (!result_maybe.ToLocal(&result)) {
      exception_state.RethrowV8Exception(trycatch.Exception());
      return base::nullopt;
    }

    // This conversion to double comes from the EnqueueValueWithSize
    // operation: https://streams.spec.whatwg.org/#enqueue-value-with-size
    // 2. Let size be ? ToNumber(size).
    v8::MaybeLocal<v8::Number> number_maybe = result->ToNumber(context);
    v8::Local<v8::Number> number;
    if (!number_maybe.ToLocal(&number)) {
      exception_state.RethrowV8Exception(trycatch.Exception());
      return base::nullopt;
    }
    return number->Value();
  }

  void Trace(Visitor* visitor) override {
    visitor->Trace(function_);
    StrategySizeAlgorithm::Trace(visitor);
  }

 private:
  TraceWrapperV8Reference<v8::Function> function_;
};

class TrivialStreamAlgorithm final : public StreamAlgorithm {
 public:
  v8::Local<v8::Promise> Run(ScriptState* script_state,
                             int argc,
                             v8::Local<v8::Value> argv[]) override {
    return PromiseResolveWithUndefined(script_state);
  }
};

class JavaScriptStreamAlgorithmWithoutExtraArg final : public StreamAlgorithm {
 public:
  JavaScriptStreamAlgorithmWithoutExtraArg(v8::Isolate* isolate,
                                           v8::Local<v8::Function> method,
                                           v8::Local<v8::Object> recv)
      : recv_(isolate, recv), method_(isolate, method) {}

  // |argc| is equivalent to the "algoArgCount" argument to
  // CreateAlgorithmFromUnderlyingMethod() in the standard, but it is
  // determined when the algorithm is called rather than when the algorithm is
  // created.
  v8::Local<v8::Promise> Run(ScriptState* script_state,
                             int argc,
                             v8::Local<v8::Value> argv[]) override {
    // This method technically supports any number of arguments, but we only
    // call it with 0 or 1 in practice.
    DCHECK_GE(argc, 0);
    auto* isolate = script_state->GetIsolate();
    // https://streams.spec.whatwg.org/#create-algorithm-from-underlying-method
    // 6.b.i. Return ! PromiseCall(method, underlyingObject, extraArgs).
    // In this class extraArgs is always empty, but there may be other arguments
    // supplied to the method.
    return PromiseCall(script_state, method_.NewLocal(isolate),
                       recv_.NewLocal(isolate), argc, argv);
  }

  void Trace(Visitor* visitor) override {
    visitor->Trace(recv_);
    visitor->Trace(method_);
    StreamAlgorithm::Trace(visitor);
  }

 private:
  TraceWrapperV8Reference<v8::Object> recv_;
  TraceWrapperV8Reference<v8::Function> method_;
};

class JavaScriptStreamAlgorithmWithExtraArg final : public StreamAlgorithm {
 public:
  JavaScriptStreamAlgorithmWithExtraArg(v8::Isolate* isolate,
                                        v8::Local<v8::Function> method,
                                        v8::Local<v8::Value> extra_arg,
                                        v8::Local<v8::Object> recv)
      : recv_(isolate, recv),
        method_(isolate, method),
        extra_arg_(isolate, extra_arg) {}

  // |argc| is equivalent to the "algoArgCount" argument to
  // CreateAlgorithmFromUnderlyingMethod() in the standard,
  v8::Local<v8::Promise> Run(ScriptState* script_state,
                             int argc,
                             v8::Local<v8::Value> argv[]) override {
    DCHECK_GE(argc, 0);
    DCHECK_LE(argc, 1);
    auto* isolate = script_state->GetIsolate();
    // https://streams.spec.whatwg.org/#create-algorithm-from-underlying-method
    // 6.c.
    //      i. Let fullArgs be a List consisting of arg followed by the
    //         elements of extraArgs in order.
    v8::Local<v8::Value> full_argv[2];
    if (argc != 0) {
      full_argv[0] = argv[0];
    }
    full_argv[argc] = extra_arg_.NewLocal(isolate);
    int full_argc = argc + 1;

    //     ii. Return ! PromiseCall(method, underlyingObject, fullArgs).
    return PromiseCall(script_state, method_.NewLocal(isolate),
                       recv_.NewLocal(isolate), full_argc, full_argv);
  }

  void Trace(Visitor* visitor) override {
    visitor->Trace(recv_);
    visitor->Trace(method_);
    visitor->Trace(extra_arg_);
    StreamAlgorithm::Trace(visitor);
  }

 private:
  TraceWrapperV8Reference<v8::Object> recv_;
  TraceWrapperV8Reference<v8::Function> method_;
  TraceWrapperV8Reference<v8::Value> extra_arg_;
};

}  // namespace

// TODO(ricea): For optimal performance, method_name should be cached as an
// atomic v8::String. It's not clear who should own the cache.
CORE_EXPORT StreamAlgorithm* CreateAlgorithmFromUnderlyingMethod(
    ScriptState* script_state,
    v8::Local<v8::Object> underlying_object,
    const char* method_name,
    const char* method_name_for_error,
    v8::MaybeLocal<v8::Value> extra_arg,
    ExceptionState& exception_state) {
  // https://streams.spec.whatwg.org/#create-algorithm-from-underlying-method
  // 5. Let method be ? GetV(underlyingObject, methodName).
  // 6. If method is not undefined,
  //    a. If ! IsCallable(method) is false, throw a TypeError exception.
  v8::MaybeLocal<v8::Value> method_maybe =
      ResolveMethod(script_state, underlying_object, method_name,
                    method_name_for_error, exception_state);
  v8::Local<v8::Value> method;
  if (!method_maybe.ToLocal(&method)) {
    DCHECK(exception_state.HadException());
    return nullptr;
  }

  if (method->IsUndefined()) {
    // 7. Return an algorithm which returns a promise resolved with undefined.
    return MakeGarbageCollected<TrivialStreamAlgorithm>();
  }
  DCHECK(method->IsFunction());

  auto* isolate = script_state->GetIsolate();

  // The standard switches on the number of arguments to be passed to the
  // algorithm, but this implementation doesn't care about that. Instead we
  // switch on whether or not there is an extraArg, as that decides whether or
  // not we need to reconstruct the argument list at runtime.
  v8::Local<v8::Value> extra_arg_local;
  if (!extra_arg.ToLocal(&extra_arg_local)) {
    return MakeGarbageCollected<JavaScriptStreamAlgorithmWithoutExtraArg>(
        isolate, method.As<v8::Function>(), underlying_object);
  }

  return MakeGarbageCollected<JavaScriptStreamAlgorithmWithExtraArg>(
      isolate, method.As<v8::Function>(), extra_arg_local, underlying_object);
}

CORE_EXPORT v8::MaybeLocal<v8::Value> CallOrNoop1(
    ScriptState* script_state,
    v8::Local<v8::Object> object,
    const char* method_name,
    const char* name_for_error,
    v8::Local<v8::Value> arg0,
    ExceptionState& exception_state) {
  // https://streams.spec.whatwg.org/#invoke-or-noop
  // 4. Let method be ? GetV(O, P).
  v8::MaybeLocal<v8::Value> method_maybe = ResolveMethod(
      script_state, object, method_name, name_for_error, exception_state);
  v8::Local<v8::Value> method;
  if (!method_maybe.ToLocal(&method)) {
    DCHECK(exception_state.HadException());
    return v8::MaybeLocal<v8::Value>();
  }

  // 5. If method is undefined, return undefined.
  if (method->IsUndefined()) {
    return v8::Undefined(script_state->GetIsolate());
  }
  DCHECK(method->IsFunction());

  // 6. Return ? Call(method, O, args).
  return method.As<v8::Function>()->Call(script_state->GetContext(), object, 1,
                                         &arg0);
}

CORE_EXPORT v8::Local<v8::Promise> PromiseCall(ScriptState* script_state,
                                               v8::Local<v8::Function> method,
                                               v8::Local<v8::Object> recv,
                                               int argc,
                                               v8::Local<v8::Value> argv[]) {
  DCHECK_GE(argc, 0);
  v8::TryCatch trycatch(script_state->GetIsolate());

  // https://streams.spec.whatwg.org/#promise-call
  // 4. Let returnValue be Call(F, V, args).
  v8::MaybeLocal<v8::Value> result_maybe =
      method->Call(script_state->GetContext(), recv, argc, argv);

  v8::Local<v8::Value> result;
  // 5. If returnValue is an abrupt completion, return a promise rejected with
  //    returnValue.[[Value]].
  if (!result_maybe.ToLocal(&result)) {
    return PromiseReject(script_state, trycatch.Exception());
  }

  // 6. Otherwise, return a promise resolved with returnValue.[[Value]].
  return PromiseResolve(script_state, result);
}

CORE_EXPORT double ValidateAndNormalizeHighWaterMark(
    double high_water_mark,
    ExceptionState& exception_state) {
  // https://streams.spec.whatwg.org/#validate-and-normalize-high-water-mark
  // 2. If highWaterMark is NaN or highWaterMark < 0, throw a RangeError
  //    exception.
  if (isnan(high_water_mark) || high_water_mark < 0) {
    exception_state.ThrowRangeError(
        "A queuing strategy's highWaterMark property must be a nonnegative, "
        "non-NaN number");
    return 0;
  }

  // 3. Return highWaterMark.
  return high_water_mark;
}

CORE_EXPORT StrategySizeAlgorithm* MakeSizeAlgorithmFromSizeFunction(
    ScriptState* script_state,
    v8::Local<v8::Value> size,
    ExceptionState& exception_state) {
  // 1. If size is undefined, return an algorithm that returns 1.
  if (size->IsUndefined()) {
    return MakeGarbageCollected<DefaultSizeAlgorithm>();
  }

  // 2. If ! IsCallable(size) is false, throw a TypeError exception.
  if (!size->IsFunction()) {
    exception_state.ThrowTypeError(
        "A queuing strategy's size property must be a function");
    return nullptr;
  }

  // 3. Return an algorithm that performs the following steps, taking a chunk
  // argument:
  //    a. Return ? Call(size, undefined, « chunk »).
  return MakeGarbageCollected<JavaScriptSizeAlgorithm>(
      script_state->GetIsolate(), size.As<v8::Function>());
}

// PromiseResolve implements Promise.resolve(_x_) from the ECMASCRIPT standard,
// https://tc39.github.io/ecma262/#sec-promise.resolve, except that the
// Get(_x_, "constructor") step is skipped.
CORE_EXPORT v8::Local<v8::Promise> PromiseResolve(ScriptState* script_state,
                                                  v8::Local<v8::Value> value) {
  if (value->IsPromise()) {
    return value.As<v8::Promise>();
  }
  auto context = script_state->GetContext();
  v8::TryCatch trycatch(script_state->GetIsolate());
  // TODO(ricea): Can this fail for reasons other than memory exhaustion? Can we
  // recover if it does?
  auto resolver = v8::Promise::Resolver::New(context).ToLocalChecked();
  if (resolver->Resolve(context, value).IsNothing()) {
    // TODO(ricea): Is this actually reachable?
    return PromiseReject(script_state, trycatch.Exception());
  }
  return resolver->GetPromise();
}

CORE_EXPORT v8::Local<v8::Promise> PromiseResolveWithUndefined(
    ScriptState* script_state) {
  return PromiseResolve(script_state,
                        v8::Undefined(script_state->GetIsolate()));
}

CORE_EXPORT v8::Local<v8::Promise> PromiseReject(ScriptState* script_state,
                                                 v8::Local<v8::Value> value) {
  return PromiseRejectInternal(script_state, value, 0);
}

}  // namespace blink
