Line data Source code
1 : // Copyright 2016 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #include "src/builtins/builtins-utils-inl.h"
6 : #include "src/builtins/builtins.h"
7 : #include "src/elements.h"
8 :
9 : #include "src/counters.h"
10 : #include "src/objects-inl.h"
11 :
12 : namespace v8 {
13 : namespace internal {
14 :
15 : namespace {
16 : enum UncurryThisFunctionContextSlot {
17 : kFunctionSlot = Context::MIN_CONTEXT_SLOTS,
18 : kFunctionContextLength,
19 : };
20 : } // namespace
21 :
22 : // These functions are key for safe meta-programming:
23 : // http://wiki.ecmascript.org/doku.php?id=conventions:safe_meta_programming
24 : //
25 : // Technically they could all be derived from combinations of
26 : // Function.prototype.{bind,call,apply} but that introduces lots of layers of
27 : // indirection.
28 : //
29 : // Equivalent to:
30 : //
31 : // function uncurryThis(func) {
32 : // return function(thisArg, ...args) {
33 : // return %reflect_apply(func, thisArg, args);
34 : // };
35 : // };
36 : //
37 1352 : BUILTIN(ExtrasUtilsUncurryThis) {
38 : HandleScope scope(isolate);
39 :
40 : DCHECK_EQ(2, args.length());
41 : Handle<JSFunction> function = args.at<JSFunction>(1);
42 : Handle<NativeContext> native_context(isolate->context()->native_context(),
43 : isolate);
44 : Handle<Context> context = isolate->factory()->NewBuiltinContext(
45 : native_context,
46 338 : static_cast<int>(UncurryThisFunctionContextSlot::kFunctionContextLength));
47 :
48 : context->set(static_cast<int>(UncurryThisFunctionContextSlot::kFunctionSlot),
49 : *function);
50 :
51 : Handle<SharedFunctionInfo> info =
52 : isolate->factory()->NewSharedFunctionInfoForBuiltin(
53 : isolate->factory()->empty_string(),
54 338 : Builtins::kExtrasUtilsCallReflectApply, kNormalFunction);
55 : info->DontAdaptArguments();
56 :
57 338 : Handle<Map> map = isolate->strict_function_without_prototype_map();
58 : Handle<JSFunction> new_bound_function =
59 338 : isolate->factory()->NewFunctionFromSharedFunctionInfo(map, info, context);
60 :
61 676 : return *new_bound_function;
62 : }
63 :
64 100 : BUILTIN(ExtrasUtilsCallReflectApply) {
65 : HandleScope scope(isolate);
66 : Handle<Context> context(isolate->context(), isolate);
67 : Handle<NativeContext> native_context(isolate->context()->native_context(),
68 : isolate);
69 : Handle<JSFunction> function(
70 : JSFunction::cast(context->get(
71 : static_cast<int>(UncurryThisFunctionContextSlot::kFunctionSlot))),
72 : isolate);
73 :
74 : Handle<Object> this_arg = args.at(1);
75 :
76 : int const rest_args_atart = 2;
77 : Arguments argv(args.length() - rest_args_atart,
78 20 : args.address_of_arg_at(rest_args_atart));
79 : Handle<JSArray> rest_args_array = isolate->factory()->NewJSArray(0);
80 40 : RETURN_FAILURE_ON_EXCEPTION(
81 : isolate, ArrayConstructInitializeElements(rest_args_array, &argv));
82 :
83 20 : Handle<Object> reflect_apply_args[] = {function, this_arg, rest_args_array};
84 40 : Handle<JSFunction> reflect_apply(native_context->reflect_apply(), isolate);
85 40 : RETURN_RESULT_OR_FAILURE(
86 : isolate,
87 : Execution::Call(isolate, reflect_apply,
88 : isolate->factory()->undefined_value(),
89 : arraysize(reflect_apply_args), reflect_apply_args));
90 : }
91 :
92 : } // namespace internal
93 121996 : } // namespace v8
|