Skip to content

Commit 5ac8cbc

Browse files
committed
[JSC] Improve our bound function implementation
https://bugs.webkit.org/show_bug.cgi?id=205327 Reviewed by Keith Miller. JSTests: * microbenchmarks/function-bind-no-inlining-repeat-call.js: Added. (assert): (test): (test2): (foo): (let.start.Date.now): * stress/bind-args.js: Added. (shouldBe): (test): (test2): Source/JavaScriptCore: This patch improves Function#bind, and calling bound function with bound arguments. 1. Rename CallFrameSlot::argumentCount to CallFrameSlot::argumentCountIncludingThis. 2. Do not include name in NativeExecutable for JSBoundFunction. Putting name in NativeExecutable is assuming that function + name pair is almost identical. This is true in host functions except for JSBoundFunction. JSBoundFunction should hold its name in JSBoundFunction. 3. Cache NativeExecutable for JSBoundFunction in the VM. We use a hash-map in JITThunk for NativeExecutables because we assume that host-function creation cannot be done by the user program: each executable is pre-defined to exactly one object by the environment, and there is no way to create host-functions repeatedly from the user-program. The only exception to this is JSBoundFunction so caching it on the VM avoids the hash-map lookup. This is not true for JSBoundFunction. 4. ThunkGenerator should support JSBoundFunction call with bound arguments. It turns out that Speedometer2/React-Redux-TodoMVC is using bound function with bound arguments. Additionally, it is used. This is really bad: when dispatching an event, we first call this function from C++, entering JS world, going back to C++ world again, and entering JS world to call bound function again. By using ThunkGenerator, we can eliminate this back and forth by directly calling the bound JS Executable from the thunk. Previously, bound arguments are stored in JSArray. But it is difficult to access them from thunk since we need to consider have-a-bad-time case. Instead, we use JSImmutableButterfly to save bound arguments so that JIT thunk can quickly access arguments. To capture arguments as JSImmutableButterfly in JS world, we introduce op_create_arguments_butterfly, and handle it in all tiers. 5. It turns out that eager materialization of "length" in JSBoundFunction takes long time while it is rarely used. This patch makes length lazily reified for JSBoundFunction. 6. To make Function.prototype.bind faster, we track whether "name" and "length" properties of JSFunction is modified or not. This skips has-own-length-property check, which makes Function.prototype.bind 11~% faster. Combining things above, creation of JSBoundFunction is 80~% faster. And calling bound function with bound arguments is 3~x faster. This improves Speedometer2/React-TodoMVC by ~3%. * builtins/FunctionPrototype.js: (bind): * bytecode/AccessCase.cpp: (JSC::AccessCase::generateImpl): * bytecode/AccessCaseSnippetParams.cpp: (JSC::SlowPathCallGeneratorWithArguments::generateImpl): * bytecode/BytecodeIntrinsicRegistry.h: * bytecode/BytecodeList.rb: * bytecode/BytecodeUseDef.cpp: (JSC::computeUsesForBytecodeIndexImpl): (JSC::computeDefsForBytecodeIndexImpl): * bytecode/VirtualRegister.cpp: (JSC::VirtualRegister::dump const): * bytecompiler/BytecodeGenerator.cpp: (JSC::BytecodeGenerator::emitCreateArgumentsButterfly): * bytecompiler/BytecodeGenerator.h: * bytecompiler/NodesCodegen.cpp: (JSC::BytecodeIntrinsicNode::emit_intrinsic_createArgumentsButterfly): * dfg/DFGAbstractInterpreterInlines.h: (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects): * dfg/DFGArgumentsEliminationPhase.cpp: * dfg/DFGArgumentsUtilities.cpp: (JSC::DFG::argumentsInvolveStackSlot): * dfg/DFGByteCodeParser.cpp: (JSC::DFG::ByteCodeParser::flushImpl): (JSC::DFG::ByteCodeParser::handleVarargsInlining): (JSC::DFG::ByteCodeParser::parseBlock): * dfg/DFGCapabilities.cpp: (JSC::DFG::capabilityLevel): * dfg/DFGClobberize.h: (JSC::DFG::clobberize): * dfg/DFGDoesGC.cpp: (JSC::DFG::doesGC): * dfg/DFGFixupPhase.cpp: (JSC::DFG::FixupPhase::fixupNode): * dfg/DFGGraph.cpp: (JSC::DFG::Graph::isLiveInBytecode): * dfg/DFGGraph.h: (JSC::DFG::Graph::forAllLocalsLiveInBytecode): * dfg/DFGJITCompiler.cpp: (JSC::DFG::JITCompiler::compileFunction): * dfg/DFGJITCompiler.h: (JSC::DFG::JITCompiler::emitStoreCallSiteIndex): * dfg/DFGNodeType.h: * dfg/DFGOSRAvailabilityAnalysisPhase.cpp: (JSC::DFG::LocalOSRAvailabilityCalculator::executeNode): * dfg/DFGOSRExit.cpp: (JSC::DFG::emitRestoreArguments): (JSC::DFG::reifyInlinedCallFrames): (JSC::DFG::OSRExit::emitRestoreArguments): * dfg/DFGOSRExitCompilerCommon.cpp: (JSC::DFG::reifyInlinedCallFrames): * dfg/DFGOperations.cpp: * dfg/DFGOperations.h: * dfg/DFGPreciseLocalClobberize.h: (JSC::DFG::PreciseLocalClobberizeAdaptor::readTop): * dfg/DFGPredictionPropagationPhase.cpp: * dfg/DFGSafeToExecute.h: (JSC::DFG::safeToExecute): * dfg/DFGSpeculativeJIT.cpp: (JSC::DFG::SpeculativeJIT::compileCreateArgumentsButterfly): (JSC::DFG::SpeculativeJIT::compileGetArgumentCountIncludingThis): (JSC::DFG::SpeculativeJIT::compileSetArgumentCountIncludingThis): * dfg/DFGSpeculativeJIT.h: * dfg/DFGSpeculativeJIT32_64.cpp: (JSC::DFG::SpeculativeJIT::emitCall): (JSC::DFG::SpeculativeJIT::compile): * dfg/DFGSpeculativeJIT64.cpp: (JSC::DFG::SpeculativeJIT::emitCall): (JSC::DFG::SpeculativeJIT::compile): * dfg/DFGStackLayoutPhase.cpp: (JSC::DFG::StackLayoutPhase::run): * dfg/DFGStoreBarrierInsertionPhase.cpp: * ftl/FTLAbstractHeapRepository.h: * ftl/FTLCapabilities.cpp: (JSC::FTL::canCompile): * ftl/FTLLink.cpp: (JSC::FTL::link): * ftl/FTLLowerDFGToB3.cpp: (JSC::FTL::DFG::LowerDFGToB3::lower): (JSC::FTL::DFG::LowerDFGToB3::compileNode): (JSC::FTL::DFG::LowerDFGToB3::compileCreateArgumentsButterfly): (JSC::FTL::DFG::LowerDFGToB3::compileGetArgumentCountIncludingThis): (JSC::FTL::DFG::LowerDFGToB3::compileSetArgumentCountIncludingThis): (JSC::FTL::DFG::LowerDFGToB3::compileCallOrConstruct): (JSC::FTL::DFG::LowerDFGToB3::compileDirectCallOrConstruct): (JSC::FTL::DFG::LowerDFGToB3::compileTailCall): (JSC::FTL::DFG::LowerDFGToB3::compileCallOrConstructVarargsSpread): (JSC::FTL::DFG::LowerDFGToB3::compileCallOrConstructVarargs): (JSC::FTL::DFG::LowerDFGToB3::compileCallEval): (JSC::FTL::DFG::LowerDFGToB3::getArgumentsLength): (JSC::FTL::DFG::LowerDFGToB3::callPreflight): * ftl/FTLSlowPathCall.h: (JSC::FTL::callOperation): * interpreter/CallFrame.cpp: (JSC::CallFrame::callSiteAsRawBits const): (JSC::CallFrame::unsafeCallSiteAsRawBits const): (JSC::CallFrame::setCurrentVPC): * interpreter/CallFrame.h: (JSC::CallFrame::argumentCountIncludingThis const): (JSC::CallFrame::setArgumentCountIncludingThis): * jit/AssemblyHelpers.cpp: (JSC::AssemblyHelpers::jitAssertArgumentCountSane): * jit/AssemblyHelpers.h: (JSC::AssemblyHelpers::argumentCount): * jit/CCallHelpers.h: (JSC::CCallHelpers::prepareForTailCallSlow): * jit/CallFrameShuffler.cpp: (JSC::CallFrameShuffler::dump const): (JSC::CallFrameShuffler::prepareForTailCall): (JSC::CallFrameShuffler::prepareAny): * jit/JIT.cpp: (JSC::JIT::privateCompileMainPass): (JSC::JIT::compileWithoutLinking): * jit/JITCall.cpp: (JSC::JIT::compileSetupFrame): (JSC::JIT::compileOpCall): * jit/JITCall32_64.cpp: (JSC::JIT::compileSetupFrame): (JSC::JIT::compileOpCall): * jit/JITInlines.h: (JSC::JIT::updateTopCallFrame): * jit/JITOpcodes.cpp: (JSC::JIT::emit_op_argument_count): (JSC::JIT::emit_op_get_rest_length): (JSC::JIT::emit_op_get_argument): * jit/SetupVarargsFrame.cpp: (JSC::emitSetupVarargsFrameFastCase): * jit/SpecializedThunkJIT.h: (JSC::SpecializedThunkJIT::SpecializedThunkJIT): * jit/ThunkGenerators.cpp: (JSC::arityFixupGenerator): (JSC::boundFunctionCallGenerator): (JSC::boundThisNoArgsFunctionCallGenerator): Deleted. * jit/ThunkGenerators.h: * jsc.cpp: * llint/LLIntData.cpp: (JSC::LLInt::Data::performAssertions): * llint/LowLevelInterpreter.asm: * llint/LowLevelInterpreter32_64.asm: * llint/LowLevelInterpreter64.asm: * llint/WebAssembly.asm: * runtime/CommonSlowPaths.cpp: (JSC::SLOW_PATH_DECL): * runtime/CommonSlowPaths.h: * runtime/ExecutableBase.h: * runtime/FunctionRareData.cpp: (JSC::FunctionRareData::FunctionRareData): * runtime/FunctionRareData.h: * runtime/IntlCollatorPrototype.cpp: (JSC::IntlCollatorPrototypeGetterCompare): * runtime/IntlDateTimeFormatPrototype.cpp: (JSC::IntlDateTimeFormatPrototypeGetterFormat): * runtime/IntlNumberFormatPrototype.cpp: (JSC::IntlNumberFormatPrototypeGetterFormat): * runtime/Intrinsic.cpp: (JSC::intrinsicName): * runtime/Intrinsic.h: * runtime/JSBoundFunction.cpp: (JSC::boundThisNoArgsFunctionCall): (JSC::boundFunctionCall): (JSC::boundThisNoArgsFunctionConstruct): (JSC::boundFunctionConstruct): (JSC::JSBoundFunction::create): (JSC::JSBoundFunction::JSBoundFunction): (JSC::JSBoundFunction::boundArgsCopy): (JSC::JSBoundFunction::visitChildren): * runtime/JSBoundFunction.h: * runtime/JSFunction.cpp: (JSC::JSFunction::finishCreation): (JSC::JSFunction::name): (JSC::JSFunction::getOwnPropertySlot): (JSC::JSFunction::getOwnNonIndexPropertyNames): (JSC::JSFunction::put): (JSC::JSFunction::deleteProperty): (JSC::JSFunction::defineOwnProperty): (JSC::JSFunction::reifyLength): (JSC::JSFunction::reifyLazyPropertyIfNeeded): (JSC::JSFunction::reifyLazyPropertyForHostOrBuiltinIfNeeded): (JSC::JSFunction::reifyLazyBoundNameIfNeeded): * runtime/JSFunction.h: * runtime/JSFunctionInlines.h: (JSC::JSFunction::areNameAndLengthOriginal): * runtime/JSGlobalObject.cpp: (JSC::makeBoundFunction): (JSC::hasOwnLengthProperty): * runtime/JSObject.h: (JSC::getJSFunction): (JSC::getCallData): Deleted. (JSC::getConstructData): Deleted. * runtime/JSObjectInlines.h: (JSC::getCallData): (JSC::getConstructData): * runtime/VM.cpp: (JSC::thunkGeneratorForIntrinsic): (JSC::VM::getBoundFunction): * runtime/VM.h: * wasm/js/WasmToJS.cpp: (JSC::Wasm::wasmToJS): * wasm/js/WebAssemblyFunction.cpp: (JSC::WebAssemblyFunction::jsCallEntrypointSlow): Tools: Support running slow-microbenchmarks. * Scripts/run-jsc-benchmarks: LayoutTests: * inspector/model/remote-object-get-properties-expected.txt: * inspector/runtime/getDisplayableProperties-expected.txt: * inspector/runtime/getProperties-expected.txt: Canonical link: https://commits.webkit.org/218747@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@253867 268f45cc-cd09-0410-ab3c-d52691b4dbfc
1 parent 9309b64 commit 5ac8cbc

95 files changed

Lines changed: 943 additions & 258 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎JSTests/ChangeLog‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,21 @@
1+
2019-12-21 Yusuke Suzuki <ysuzuki@apple.com>
2+
3+
[JSC] Improve our bound function implementation
4+
https://bugs.webkit.org/show_bug.cgi?id=205327
5+
6+
Reviewed by Keith Miller.
7+
8+
* microbenchmarks/function-bind-no-inlining-repeat-call.js: Added.
9+
(assert):
10+
(test):
11+
(test2):
12+
(foo):
13+
(let.start.Date.now):
14+
* stress/bind-args.js: Added.
15+
(shouldBe):
16+
(test):
17+
(test2):
18+
119
2019-12-17 Yusuke Suzuki <ysuzuki@apple.com>
220

321
[JSC] 8Bit JSRopeString can contain 16Bit string in its rope
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
2+
function assert(b) {
3+
if (!b)
4+
throw new Error("Bad")
5+
}
6+
noInline(assert);
7+
8+
function test(f, v, c, d) {
9+
return f.bind(v, c, d);
10+
}
11+
noInline(test);
12+
13+
function test2(f, v) {
14+
return f.bind(v);
15+
}
16+
noInline(test);
17+
18+
function foo(a,b,c,d,e,f) { return this; }
19+
let thisValue = {};
20+
let start = Date.now();
21+
22+
{
23+
let f = test(foo, thisValue, 20, 30);
24+
for (let i = 0; i < 1000000; i++) {
25+
assert(f(foo, thisValue, 20, 30) === thisValue);
26+
}
27+
}
28+
{
29+
let f = test2(foo, thisValue);
30+
for (let i = 0; i < 1000000; i++) {
31+
assert(f(foo, thisValue, 20, 30) === thisValue);
32+
}
33+
}
34+
const verbose = false;
35+
if (verbose)
36+
print(Date.now() - start);

‎JSTests/stress/bind-args.js‎

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
function shouldBe(actual, expected) {
2+
if (actual !== expected)
3+
throw new Error('bad value: ' + actual);
4+
}
5+
noInline(shouldBe);
6+
7+
function test(a, b, c, d, e)
8+
{
9+
return a + b + c + d + e;
10+
}
11+
noInline(test);
12+
13+
function test2(a, b, c, d, e, f)
14+
{
15+
return a + b + c + d + e + f;
16+
}
17+
noInline(test2);
18+
19+
for (var i = 0; i < 3e4; ++i) {
20+
shouldBe(test.bind(undefined)(1, 2, 3, 4, 5), 15);
21+
shouldBe(test.bind(undefined, 1)(2, 3, 4, 5), 15);
22+
shouldBe(test.bind(undefined, 2, 3)(4, 5, 6), 20);
23+
shouldBe(test.bind(undefined, 2, 3, 4)(5, 6), 20);
24+
shouldBe(test.bind(undefined, 2, 3, 4, 5)(6), 20);
25+
shouldBe(test.bind(undefined, 2, 3, 4, 5, 6)(), 20);
26+
27+
shouldBe(test2.bind(undefined)(1, 1, 2, 3, 4, 5), 16);
28+
shouldBe(test2.bind(undefined, 1)(1, 2, 3, 4, 5), 16);
29+
shouldBe(test2.bind(undefined, 1, 1)(2, 3, 4, 5), 16);
30+
shouldBe(test2.bind(undefined, 1, 2, 3)(4, 5, 6), 21);
31+
shouldBe(test2.bind(undefined, 1, 2, 3, 4)(5, 6), 21);
32+
shouldBe(test2.bind(undefined, 1, 2, 3, 4, 5)(6), 21);
33+
shouldBe(test2.bind(undefined, 1, 2, 3, 4, 5, 6)(), 21);
34+
}

‎LayoutTests/ChangeLog‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,14 @@
1+
2019-12-21 Yusuke Suzuki <ysuzuki@apple.com>
2+
3+
[JSC] Improve our bound function implementation
4+
https://bugs.webkit.org/show_bug.cgi?id=205327
5+
6+
Reviewed by Keith Miller.
7+
8+
* inspector/model/remote-object-get-properties-expected.txt:
9+
* inspector/runtime/getDisplayableProperties-expected.txt:
10+
* inspector/runtime/getProperties-expected.txt:
11+
112
2019-12-21 Kate Cheney <katherine_cheney@apple.com>
213

314
Add timeStamp to ITP database

‎LayoutTests/inspector/model/remote-object-get-properties-expected.txt‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -407,8 +407,8 @@ description: function unboundFunction() {
407407
}
408408

409409
OWN PROPERTIES:
410-
name
411410
length
411+
name
412412
__proto__
413413
targetFunction
414414
boundThis

‎LayoutTests/inspector/runtime/getDisplayableProperties-expected.txt‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ Properties:
3333
Evaluating expression...
3434
Getting displayable properties...
3535
Properties:
36-
"name" => "bound Test" (string) [configurable | isOwn]
3736
"length" => 0 (number) [configurable | isOwn]
37+
"name" => "bound Test" (string) [configurable | isOwn]
3838
"caller" => "TypeError: 'arguments', 'callee', and 'caller' cannot be accessed in this context." (object error) [wasThrown]
3939
"arguments" => "TypeError: 'arguments', 'callee', and 'caller' cannot be accessed in this context." (object error) [wasThrown]
4040
"__proto__" => "function () {\n [native code]\n}" (function) [writable | configurable | isOwn]
@@ -46,8 +46,8 @@ Internal Properties:
4646
Evaluating expression...
4747
Getting displayable properties...
4848
Properties:
49-
"name" => "bound Test" (string) [configurable | isOwn]
5049
"length" => 0 (number) [configurable | isOwn]
50+
"name" => "bound Test" (string) [configurable | isOwn]
5151
"caller" => "TypeError: 'arguments', 'callee', and 'caller' cannot be accessed in this context." (object error) [wasThrown]
5252
"arguments" => "TypeError: 'arguments', 'callee', and 'caller' cannot be accessed in this context." (object error) [wasThrown]
5353
"__proto__" => "function () {\n [native code]\n}" (function) [writable | configurable | isOwn]
@@ -82,8 +82,8 @@ Properties:
8282
Evaluating expression...
8383
Getting displayable properties...
8484
Properties:
85-
"name" => "bound " (string) [configurable | isOwn]
8685
"length" => 3 (number) [configurable | isOwn]
86+
"name" => "bound " (string) [configurable | isOwn]
8787
"caller" => "TypeError: 'arguments', 'callee', and 'caller' cannot be accessed in this context." (object error) [wasThrown]
8888
"arguments" => "TypeError: 'arguments', 'callee', and 'caller' cannot be accessed in this context." (object error) [wasThrown]
8989
"__proto__" => "function () {\n [native code]\n}" (function) [writable | configurable | isOwn]
@@ -95,8 +95,8 @@ Internal Properties:
9595
Evaluating expression...
9696
Getting displayable properties...
9797
Properties:
98-
"name" => "bound " (string) [configurable | isOwn]
9998
"length" => 0 (number) [configurable | isOwn]
99+
"name" => "bound " (string) [configurable | isOwn]
100100
"caller" => "TypeError: 'arguments', 'callee', and 'caller' cannot be accessed in this context." (object error) [wasThrown]
101101
"arguments" => "TypeError: 'arguments', 'callee', and 'caller' cannot be accessed in this context." (object error) [wasThrown]
102102
"__proto__" => "function () {\n [native code]\n}" (function) [writable | configurable | isOwn]
@@ -109,8 +109,8 @@ Internal Properties:
109109
Evaluating expression...
110110
Getting displayable properties...
111111
Properties:
112-
"name" => "bound " (string) [configurable | isOwn]
113112
"length" => 0 (number) [configurable | isOwn]
113+
"name" => "bound " (string) [configurable | isOwn]
114114
"caller" => "TypeError: 'arguments', 'callee', and 'caller' cannot be accessed in this context." (object error) [wasThrown]
115115
"arguments" => "TypeError: 'arguments', 'callee', and 'caller' cannot be accessed in this context." (object error) [wasThrown]
116116
"__proto__" => "function () {\n [native code]\n}" (function) [writable | configurable | isOwn]
@@ -122,8 +122,8 @@ Internal Properties:
122122
Evaluating expression...
123123
Getting displayable properties...
124124
Properties:
125-
"name" => "bound " (string) [configurable | isOwn]
126125
"length" => 0 (number) [configurable | isOwn]
126+
"name" => "bound " (string) [configurable | isOwn]
127127
"caller" => "TypeError: 'arguments', 'callee', and 'caller' cannot be accessed in this context." (object error) [wasThrown]
128128
"arguments" => "TypeError: 'arguments', 'callee', and 'caller' cannot be accessed in this context." (object error) [wasThrown]
129129
"__proto__" => "function () {\n [native code]\n}" (function) [writable | configurable | isOwn]

‎LayoutTests/inspector/runtime/getProperties-expected.txt‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ Properties:
3131
Evaluating expression...
3232
Getting own properties...
3333
Properties:
34-
"name" => "bound Test" (string) [configurable | isOwn]
3534
"length" => 0 (number) [configurable | isOwn]
35+
"name" => "bound Test" (string) [configurable | isOwn]
3636
"__proto__" => "function () {\n [native code]\n}" (function) [writable | configurable | isOwn]
3737
Internal Properties:
3838
"targetFunction" => "class Test { }" (function class) []
@@ -42,8 +42,8 @@ Internal Properties:
4242
Evaluating expression...
4343
Getting own properties...
4444
Properties:
45-
"name" => "bound Test" (string) [configurable | isOwn]
4645
"length" => 0 (number) [configurable | isOwn]
46+
"name" => "bound Test" (string) [configurable | isOwn]
4747
"__proto__" => "function () {\n [native code]\n}" (function) [writable | configurable | isOwn]
4848
Internal Properties:
4949
"targetFunction" => "class Test { }" (function class) []
@@ -76,8 +76,8 @@ Properties:
7676
Evaluating expression...
7777
Getting own properties...
7878
Properties:
79-
"name" => "bound " (string) [configurable | isOwn]
8079
"length" => 3 (number) [configurable | isOwn]
80+
"name" => "bound " (string) [configurable | isOwn]
8181
"__proto__" => "function () {\n [native code]\n}" (function) [writable | configurable | isOwn]
8282
Internal Properties:
8383
"targetFunction" => "function (a, b, c){}" (function) []
@@ -87,8 +87,8 @@ Internal Properties:
8787
Evaluating expression...
8888
Getting own properties...
8989
Properties:
90-
"name" => "bound " (string) [configurable | isOwn]
9190
"length" => 0 (number) [configurable | isOwn]
91+
"name" => "bound " (string) [configurable | isOwn]
9292
"__proto__" => "function () {\n [native code]\n}" (function) [writable | configurable | isOwn]
9393
Internal Properties:
9494
"targetFunction" => "function (a, b, c){}" (function) []
@@ -99,8 +99,8 @@ Internal Properties:
9999
Evaluating expression...
100100
Getting own properties...
101101
Properties:
102-
"name" => "bound " (string) [configurable | isOwn]
103102
"length" => 0 (number) [configurable | isOwn]
103+
"name" => "bound " (string) [configurable | isOwn]
104104
"__proto__" => "function () {\n [native code]\n}" (function) [writable | configurable | isOwn]
105105
Internal Properties:
106106
"targetFunction" => "function (){}" (function) []
@@ -110,8 +110,8 @@ Internal Properties:
110110
Evaluating expression...
111111
Getting own properties...
112112
Properties:
113-
"name" => "bound " (string) [configurable | isOwn]
114113
"length" => 0 (number) [configurable | isOwn]
114+
"name" => "bound " (string) [configurable | isOwn]
115115
"__proto__" => "function () {\n [native code]\n}" (function) [writable | configurable | isOwn]
116116
Internal Properties:
117117
"targetFunction" => "function (){}" (function) []

0 commit comments

Comments
 (0)