[runtime] Implement %_ToLength via ToLengthStub.
Use %_ToLength for TO_LENGTH, implemented via a ToLengthStub that supports a fast path for small integers. Everything else is still handled in the runtime. CQ_INCLUDE_TRYBOTS=tryserver.v8:v8_linux_nosnap_rel BUG=v8:4494 LOG=n Review URL: https://codereview.chromium.org/1412963002 Cr-Commit-Position: refs/heads/master@{#31358}
This commit is contained in:
parent
51cb4481a9
commit
e678a0f9a9
@ -3168,6 +3168,21 @@ void ToNumberStub::Generate(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void ToLengthStub::Generate(MacroAssembler* masm) {
|
||||
// The ToLength stub takes one argument in r0.
|
||||
Label not_smi;
|
||||
__ JumpIfNotSmi(r0, ¬_smi);
|
||||
STATIC_ASSERT(kSmiTag == 0);
|
||||
__ tst(r0, r0);
|
||||
__ mov(r0, Operand(0), LeaveCC, lt);
|
||||
__ Ret();
|
||||
__ bind(¬_smi);
|
||||
|
||||
__ push(r0); // Push argument.
|
||||
__ TailCallRuntime(Runtime::kToLength, 1, 1);
|
||||
}
|
||||
|
||||
|
||||
void ToStringStub::Generate(MacroAssembler* masm) {
|
||||
// The ToString stub takes one argument in r0.
|
||||
Label is_number;
|
||||
|
@ -101,6 +101,10 @@ void ToNumberDescriptor::InitializePlatformSpecific(
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
const Register ToLengthDescriptor::ReceiverRegister() { return r0; }
|
||||
|
||||
|
||||
// static
|
||||
const Register ToStringDescriptor::ReceiverRegister() { return r0; }
|
||||
|
||||
|
@ -3914,6 +3914,21 @@ void ToNumberStub::Generate(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void ToLengthStub::Generate(MacroAssembler* masm) {
|
||||
// The ToLength stub takes one argument in x0.
|
||||
Label not_smi;
|
||||
__ JumpIfNotSmi(x0, ¬_smi);
|
||||
STATIC_ASSERT(kSmiTag == 0);
|
||||
__ Tst(x0, x0);
|
||||
__ Csel(x0, x0, Operand(0), ge);
|
||||
__ Ret();
|
||||
__ Bind(¬_smi);
|
||||
|
||||
__ Push(x0); // Push argument.
|
||||
__ TailCallRuntime(Runtime::kToLength, 1, 1);
|
||||
}
|
||||
|
||||
|
||||
void ToStringStub::Generate(MacroAssembler* masm) {
|
||||
// The ToString stub takes one argument in x0.
|
||||
Label is_number;
|
||||
|
@ -102,6 +102,10 @@ void ToNumberDescriptor::InitializePlatformSpecific(
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
const Register ToLengthDescriptor::ReceiverRegister() { return x0; }
|
||||
|
||||
|
||||
// static
|
||||
const Register ToStringDescriptor::ReceiverRegister() { return x0; }
|
||||
|
||||
|
@ -182,6 +182,13 @@ Callable CodeFactory::ToString(Isolate* isolate) {
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
Callable CodeFactory::ToLength(Isolate* isolate) {
|
||||
ToLengthStub stub(isolate);
|
||||
return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
Callable CodeFactory::ToObject(Isolate* isolate) {
|
||||
ToObjectStub stub(isolate);
|
||||
|
@ -74,6 +74,7 @@ class CodeFactory final {
|
||||
|
||||
static Callable ToNumber(Isolate* isolate);
|
||||
static Callable ToString(Isolate* isolate);
|
||||
static Callable ToLength(Isolate* isolate);
|
||||
static Callable ToObject(Isolate* isolate);
|
||||
|
||||
static Callable StringAdd(Isolate* isolate, StringAddFlags flags,
|
||||
|
@ -52,6 +52,7 @@ namespace internal {
|
||||
V(StubFailureTrampoline) \
|
||||
V(SubString) \
|
||||
V(ToNumber) \
|
||||
V(ToLength) \
|
||||
V(ToString) \
|
||||
V(ToObject) \
|
||||
V(VectorStoreICTrampoline) \
|
||||
@ -3076,6 +3077,15 @@ class ToNumberStub final : public PlatformCodeStub {
|
||||
};
|
||||
|
||||
|
||||
class ToLengthStub final : public PlatformCodeStub {
|
||||
public:
|
||||
explicit ToLengthStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
|
||||
|
||||
DEFINE_CALL_INTERFACE_DESCRIPTOR(ToLength);
|
||||
DEFINE_PLATFORM_CODE_STUB(ToLength, PlatformCodeStub);
|
||||
};
|
||||
|
||||
|
||||
class ToStringStub final : public PlatformCodeStub {
|
||||
public:
|
||||
explicit ToStringStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
|
||||
|
@ -3797,6 +3797,19 @@ void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitToLength(CallRuntime* expr) {
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
DCHECK_EQ(1, args->length());
|
||||
|
||||
// Load the argument into r0 and convert it.
|
||||
VisitForAccumulatorValue(args->at(0));
|
||||
|
||||
ToLengthStub stub(isolate());
|
||||
__ CallStub(&stub);
|
||||
context()->Plug(r0);
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitToString(CallRuntime* expr) {
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
DCHECK_EQ(1, args->length());
|
||||
|
@ -3507,6 +3507,19 @@ void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitToLength(CallRuntime* expr) {
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
DCHECK_EQ(1, args->length());
|
||||
|
||||
// Load the argument into x0 and convert it.
|
||||
VisitForAccumulatorValue(args->at(0));
|
||||
|
||||
ToLengthStub stub(isolate());
|
||||
__ CallStub(&stub);
|
||||
context()->Plug(x0);
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitToString(CallRuntime* expr) {
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
DCHECK_EQ(1, args->length());
|
||||
|
@ -518,6 +518,7 @@ class FullCodeGenerator: public AstVisitor {
|
||||
F(ToInteger) \
|
||||
F(NumberToString) \
|
||||
F(ToString) \
|
||||
F(ToLength) \
|
||||
F(ToNumber) \
|
||||
F(ToName) \
|
||||
F(ToObject) \
|
||||
|
@ -3695,6 +3695,19 @@ void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitToLength(CallRuntime* expr) {
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
DCHECK_EQ(1, args->length());
|
||||
|
||||
// Load the argument into eax and convert it.
|
||||
VisitForAccumulatorValue(args->at(0));
|
||||
|
||||
ToLengthStub stub(isolate());
|
||||
__ CallStub(&stub);
|
||||
context()->Plug(eax);
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitToString(CallRuntime* expr) {
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
DCHECK_EQ(1, args->length());
|
||||
|
@ -3811,6 +3811,20 @@ void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitToLength(CallRuntime* expr) {
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
DCHECK_EQ(1, args->length());
|
||||
|
||||
// Load the argument into a0 and convert it.
|
||||
VisitForAccumulatorValue(args->at(0));
|
||||
__ mov(a0, result_register());
|
||||
|
||||
ToLengthStub stub(isolate());
|
||||
__ CallStub(&stub);
|
||||
context()->Plug(v0);
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitToString(CallRuntime* expr) {
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
DCHECK_EQ(1, args->length());
|
||||
|
@ -3814,6 +3814,20 @@ void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitToLength(CallRuntime* expr) {
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
DCHECK_EQ(1, args->length());
|
||||
|
||||
// Load the argument into a0 and convert it.
|
||||
VisitForAccumulatorValue(args->at(0));
|
||||
__ mov(a0, result_register());
|
||||
|
||||
ToLengthStub stub(isolate());
|
||||
__ CallStub(&stub);
|
||||
context()->Plug(v0);
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitToString(CallRuntime* expr) {
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
DCHECK_EQ(1, args->length());
|
||||
|
@ -3704,6 +3704,19 @@ void FullCodeGenerator::EmitToString(CallRuntime* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitToLength(CallRuntime* expr) {
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
DCHECK_EQ(1, args->length());
|
||||
|
||||
// Load the argument into rax and convert it.
|
||||
VisitForAccumulatorValue(args->at(0));
|
||||
|
||||
ToLengthStub stub(isolate());
|
||||
__ CallStub(&stub);
|
||||
context()->Plug(rax);
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitToNumber(CallRuntime* expr) {
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
DCHECK_EQ(1, args->length());
|
||||
|
@ -12285,6 +12285,20 @@ void HOptimizedGraphBuilder::GenerateToString(CallRuntime* call) {
|
||||
}
|
||||
|
||||
|
||||
void HOptimizedGraphBuilder::GenerateToLength(CallRuntime* call) {
|
||||
DCHECK_EQ(1, call->arguments()->length());
|
||||
CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
|
||||
Callable callable = CodeFactory::ToLength(isolate());
|
||||
HValue* input = Pop();
|
||||
HValue* stub = Add<HConstant>(callable.code());
|
||||
HValue* values[] = {context(), input};
|
||||
HInstruction* result =
|
||||
New<HCallWithDescriptor>(stub, 0, callable.descriptor(),
|
||||
Vector<HValue*>(values, arraysize(values)));
|
||||
return ast_context()->ReturnInstruction(result, call->id());
|
||||
}
|
||||
|
||||
|
||||
void HOptimizedGraphBuilder::GenerateToNumber(CallRuntime* call) {
|
||||
DCHECK_EQ(1, call->arguments()->length());
|
||||
CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
|
||||
|
@ -2226,6 +2226,7 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
|
||||
F(ToInteger) \
|
||||
F(ToObject) \
|
||||
F(ToString) \
|
||||
F(ToLength) \
|
||||
F(ToNumber) \
|
||||
F(IsFunction) \
|
||||
F(IsSpecObject) \
|
||||
|
@ -3192,6 +3192,25 @@ void ToNumberStub::Generate(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void ToLengthStub::Generate(MacroAssembler* masm) {
|
||||
// The ToLength stub takes on argument in eax.
|
||||
Label not_smi, positive_smi;
|
||||
__ JumpIfNotSmi(eax, ¬_smi, Label::kNear);
|
||||
STATIC_ASSERT(kSmiTag == 0);
|
||||
__ test(eax, eax);
|
||||
__ j(greater_equal, &positive_smi, Label::kNear);
|
||||
__ xor_(eax, eax);
|
||||
__ bind(&positive_smi);
|
||||
__ Ret();
|
||||
__ bind(¬_smi);
|
||||
|
||||
__ pop(ecx); // Pop return address.
|
||||
__ push(eax); // Push argument.
|
||||
__ push(ecx); // Push return address.
|
||||
__ TailCallRuntime(Runtime::kToLength, 1, 1);
|
||||
}
|
||||
|
||||
|
||||
void ToStringStub::Generate(MacroAssembler* masm) {
|
||||
// The ToString stub takes one argument in eax.
|
||||
Label is_number;
|
||||
|
@ -105,6 +105,10 @@ void ToNumberDescriptor::InitializePlatformSpecific(
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
const Register ToLengthDescriptor::ReceiverRegister() { return eax; }
|
||||
|
||||
|
||||
// static
|
||||
const Register ToStringDescriptor::ReceiverRegister() { return eax; }
|
||||
|
||||
|
@ -189,6 +189,13 @@ void StringCompareDescriptor::InitializePlatformSpecific(
|
||||
}
|
||||
|
||||
|
||||
void ToLengthDescriptor::InitializePlatformSpecific(
|
||||
CallInterfaceDescriptorData* data) {
|
||||
Register registers[] = {ReceiverRegister()};
|
||||
data->InitializePlatformSpecific(arraysize(registers), registers);
|
||||
}
|
||||
|
||||
|
||||
void ToStringDescriptor::InitializePlatformSpecific(
|
||||
CallInterfaceDescriptorData* data) {
|
||||
Register registers[] = {ReceiverRegister()};
|
||||
|
@ -25,6 +25,7 @@ class PlatformInterfaceDescriptor;
|
||||
V(FastNewClosure) \
|
||||
V(FastNewContext) \
|
||||
V(ToNumber) \
|
||||
V(ToLength) \
|
||||
V(ToString) \
|
||||
V(ToObject) \
|
||||
V(NumberToString) \
|
||||
@ -373,6 +374,16 @@ class ToNumberDescriptor : public CallInterfaceDescriptor {
|
||||
};
|
||||
|
||||
|
||||
class ToLengthDescriptor : public CallInterfaceDescriptor {
|
||||
public:
|
||||
enum ParameterIndices { kReceiverIndex };
|
||||
|
||||
DECLARE_DESCRIPTOR(ToLengthDescriptor, CallInterfaceDescriptor)
|
||||
|
||||
static const Register ReceiverRegister();
|
||||
};
|
||||
|
||||
|
||||
class ToStringDescriptor : public CallInterfaceDescriptor {
|
||||
public:
|
||||
enum ParameterIndices { kReceiverIndex };
|
||||
|
@ -146,7 +146,7 @@ macro TO_INTEGER(arg) = (%_ToInteger(arg));
|
||||
macro TO_INTEGER_MAP_MINUS_ZERO(arg) = (%_IsSmi(%IS_VAR(arg)) ? arg : %NumberToIntegerMapMinusZero(arg));
|
||||
macro TO_INT32(arg) = ((arg) | 0);
|
||||
macro TO_UINT32(arg) = ((arg) >>> 0);
|
||||
macro TO_LENGTH(arg) = (%ToLength(arg));
|
||||
macro TO_LENGTH(arg) = (%_ToLength(arg));
|
||||
macro TO_LENGTH_OR_UINT32(arg) = (FLAG_harmony_tolength ? TO_LENGTH(arg) : TO_UINT32(arg));
|
||||
macro TO_LENGTH_OR_INTEGER(arg) = (FLAG_harmony_tolength ? TO_LENGTH(arg) : TO_INTEGER(arg));
|
||||
macro TO_STRING(arg) = (%_ToString(arg));
|
||||
|
@ -3314,6 +3314,23 @@ void ToNumberStub::Generate(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void ToLengthStub::Generate(MacroAssembler* masm) {
|
||||
// The ToLength stub takes on argument in a0.
|
||||
Label not_smi, positive_smi;
|
||||
__ JumpIfNotSmi(a0, ¬_smi);
|
||||
STATIC_ASSERT(kSmiTag == 0);
|
||||
__ Branch(&positive_smi, ge, a0, Operand(zero_reg));
|
||||
__ mov(a0, zero_reg);
|
||||
__ bind(&positive_smi);
|
||||
__ Ret(USE_DELAY_SLOT);
|
||||
__ mov(v0, a0);
|
||||
__ bind(¬_smi);
|
||||
|
||||
__ push(a0); // Push argument.
|
||||
__ TailCallRuntime(Runtime::kToLength, 1, 1);
|
||||
}
|
||||
|
||||
|
||||
void ToStringStub::Generate(MacroAssembler* masm) {
|
||||
// The ToString stub takes on argument in a0.
|
||||
Label is_number;
|
||||
|
@ -99,6 +99,10 @@ void ToNumberDescriptor::InitializePlatformSpecific(
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
const Register ToLengthDescriptor::ReceiverRegister() { return a0; }
|
||||
|
||||
|
||||
// static
|
||||
const Register ToStringDescriptor::ReceiverRegister() { return a0; }
|
||||
|
||||
|
@ -3348,6 +3348,23 @@ void ToNumberStub::Generate(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void ToLengthStub::Generate(MacroAssembler* masm) {
|
||||
// The ToLength stub takes on argument in a0.
|
||||
Label not_smi, positive_smi;
|
||||
__ JumpIfNotSmi(a0, ¬_smi);
|
||||
STATIC_ASSERT(kSmiTag == 0);
|
||||
__ Branch(&positive_smi, ge, a0, Operand(zero_reg));
|
||||
__ mov(a0, zero_reg);
|
||||
__ bind(&positive_smi);
|
||||
__ Ret(USE_DELAY_SLOT);
|
||||
__ mov(v0, a0);
|
||||
__ bind(¬_smi);
|
||||
|
||||
__ push(a0); // Push argument.
|
||||
__ TailCallRuntime(Runtime::kToLength, 1, 1);
|
||||
}
|
||||
|
||||
|
||||
void ToStringStub::Generate(MacroAssembler* masm) {
|
||||
// The ToString stub takes on argument in a0.
|
||||
Label is_number;
|
||||
|
@ -99,6 +99,10 @@ void ToNumberDescriptor::InitializePlatformSpecific(
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
const Register ToLengthDescriptor::ReceiverRegister() { return a0; }
|
||||
|
||||
|
||||
// static
|
||||
const Register ToStringDescriptor::ReceiverRegister() { return a0; }
|
||||
|
||||
|
@ -3122,6 +3122,25 @@ void ToNumberStub::Generate(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void ToLengthStub::Generate(MacroAssembler* masm) {
|
||||
// The ToLength stub takes on argument in rax.
|
||||
Label not_smi, positive_smi;
|
||||
__ JumpIfNotSmi(rax, ¬_smi, Label::kNear);
|
||||
STATIC_ASSERT(kSmiTag == 0);
|
||||
__ testp(rax, rax);
|
||||
__ j(greater_equal, &positive_smi, Label::kNear);
|
||||
__ xorl(rax, rax);
|
||||
__ bind(&positive_smi);
|
||||
__ Ret();
|
||||
__ bind(¬_smi);
|
||||
|
||||
__ PopReturnAddressTo(rcx); // Pop return address.
|
||||
__ Push(rax); // Push argument.
|
||||
__ PushReturnAddressFrom(rcx); // Push return address.
|
||||
__ TailCallRuntime(Runtime::kToLength, 1, 1);
|
||||
}
|
||||
|
||||
|
||||
void ToStringStub::Generate(MacroAssembler* masm) {
|
||||
// The ToString stub takes one argument in rax.
|
||||
Label is_number;
|
||||
|
@ -107,6 +107,10 @@ void ToNumberDescriptor::InitializePlatformSpecific(
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
const Register ToLengthDescriptor::ReceiverRegister() { return rax; }
|
||||
|
||||
|
||||
// static
|
||||
const Register ToStringDescriptor::ReceiverRegister() { return rax; }
|
||||
|
||||
|
76
test/mjsunit/harmony/to-length.js
Normal file
76
test/mjsunit/harmony/to-length.js
Normal file
@ -0,0 +1,76 @@
|
||||
// Copyright 2015 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.
|
||||
|
||||
// Flags: --allow-natives-syntax
|
||||
|
||||
assertEquals(0, %ToLength(NaN));
|
||||
assertEquals(0, %_ToLength(NaN));
|
||||
|
||||
assertEquals(0, %ToLength(-Infinity));
|
||||
assertEquals(0, %_ToLength(-Infinity));
|
||||
|
||||
assertEquals(0, %ToLength(0));
|
||||
assertEquals(0, %_ToLength(0));
|
||||
|
||||
assertEquals(0, %ToLength(.5));
|
||||
assertEquals(0, %_ToLength(.5));
|
||||
|
||||
assertEquals(42, %ToLength(42.99999));
|
||||
assertEquals(42, %_ToLength(42.99999));
|
||||
|
||||
assertEquals(9007199254740991, %ToLength(9007199254740991));
|
||||
assertEquals(9007199254740991, %_ToLength(9007199254740991));
|
||||
|
||||
assertEquals(9007199254740991, %ToLength(Infinity));
|
||||
assertEquals(9007199254740991, %_ToLength(Infinity));
|
||||
|
||||
assertEquals(0, %ToLength(null));
|
||||
assertEquals(0, %_ToLength(null));
|
||||
|
||||
assertEquals(1, %ToLength(true));
|
||||
assertEquals(1, %_ToLength(true));
|
||||
|
||||
assertEquals(0, %ToLength(false));
|
||||
assertEquals(0, %_ToLength(false));
|
||||
|
||||
assertEquals(0, %ToLength(undefined));
|
||||
assertEquals(0, %_ToLength(undefined));
|
||||
|
||||
assertEquals(0, %ToLength("-1"));
|
||||
assertEquals(0, %_ToLength("-1"));
|
||||
assertEquals(123, %ToLength("123"));
|
||||
assertEquals(123, %_ToLength("123"));
|
||||
assertEquals(0, %ToLength("random text"));
|
||||
assertEquals(0, %_ToLength("random text"));
|
||||
|
||||
assertThrows(function() { %ToLength(Symbol.toPrimitive) }, TypeError);
|
||||
assertThrows(function() { %_ToLength(Symbol.toPrimitive) }, TypeError);
|
||||
|
||||
var a = { toString: function() { return 54321 }};
|
||||
assertEquals(54321, %ToLength(a));
|
||||
assertEquals(54321, %_ToLength(a));
|
||||
|
||||
var b = { valueOf: function() { return 42 }};
|
||||
assertEquals(42, %ToLength(b));
|
||||
assertEquals(42, %_ToLength(b));
|
||||
|
||||
var c = {
|
||||
toString: function() { return "x"},
|
||||
valueOf: function() { return 123 }
|
||||
};
|
||||
assertEquals(123, %ToLength(c));
|
||||
assertEquals(123, %_ToLength(c));
|
||||
|
||||
var d = {
|
||||
[Symbol.toPrimitive]: function(hint) {
|
||||
assertEquals("number", hint);
|
||||
return 987654321;
|
||||
}
|
||||
};
|
||||
assertEquals(987654321, %ToLength(d));
|
||||
assertEquals(987654321, %_ToLength(d));
|
||||
|
||||
var e = new Date(0);
|
||||
assertEquals(0, %ToLength(e));
|
||||
assertEquals(0, %_ToLength(e));
|
Loading…
Reference in New Issue
Block a user