blob: 10368c0484006da8178dcec8f90981e58633374d [file] [log] [blame]
// 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-inl.h"
#include "src/builtins/builtins.h"
#include "src/objects/elements.h"
#include "src/logging/counters.h"
#include "src/objects/objects-inl.h"
namespace v8 {
namespace internal {
namespace {
enum UncurryThisFunctionContextSlot {
kFunctionSlot = Context::MIN_CONTEXT_SLOTS,
kFunctionContextLength,
};
} // namespace
// These functions are key for safe meta-programming:
// http://wiki.ecmascript.org/doku.php?id=conventions:safe_meta_programming
//
// Technically they could all be derived from combinations of
// Function.prototype.{bind,call,apply} but that introduces lots of layers of
// indirection.
//
// Equivalent to:
//
// function uncurryThis(func) {
// return function(thisArg, ...args) {
// return %reflect_apply(func, thisArg, args);
// };
// };
//
BUILTIN(ExtrasUtilsUncurryThis) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
Handle<JSFunction> function = args.at<JSFunction>(1);
Handle<NativeContext> native_context(isolate->context().native_context(),
isolate);
Handle<Context> context = isolate->factory()->NewBuiltinContext(
native_context,
static_cast<int>(UncurryThisFunctionContextSlot::kFunctionContextLength));
context->set(static_cast<int>(UncurryThisFunctionContextSlot::kFunctionSlot),
*function);
Handle<SharedFunctionInfo> info =
isolate->factory()->NewSharedFunctionInfoForBuiltin(
isolate->factory()->empty_string(),
Builtins::kExtrasUtilsCallReflectApply, kNormalFunction);
info->DontAdaptArguments();
Handle<Map> map = isolate->strict_function_without_prototype_map();
Handle<JSFunction> new_bound_function =
isolate->factory()->NewFunctionFromSharedFunctionInfo(map, info, context);
return *new_bound_function;
}
BUILTIN(ExtrasUtilsCallReflectApply) {
HandleScope scope(isolate);
Handle<Context> context(isolate->context(), isolate);
Handle<NativeContext> native_context(isolate->context().native_context(),
isolate);
Handle<JSFunction> function(
JSFunction::cast(context->get(
static_cast<int>(UncurryThisFunctionContextSlot::kFunctionSlot))),
isolate);
Handle<Object> this_arg = args.at(1);
int const rest_args_atart = 2;
Arguments argv(args.length() - rest_args_atart,
args.address_of_arg_at(rest_args_atart));
Handle<JSArray> rest_args_array = isolate->factory()->NewJSArray(0);
RETURN_FAILURE_ON_EXCEPTION(
isolate, ArrayConstructInitializeElements(rest_args_array, &argv));
Handle<Object> reflect_apply_args[] = {function, this_arg, rest_args_array};
Handle<JSFunction> reflect_apply(native_context->reflect_apply(), isolate);
RETURN_RESULT_OR_FAILURE(
isolate,
Execution::Call(isolate, reflect_apply,
isolate->factory()->undefined_value(),
arraysize(reflect_apply_args), reflect_apply_args));
}
} // namespace internal
} // namespace v8