source: webkit/trunk/JavaScriptCore/runtime/JSValue.cpp@ 73091

Last change on this file since 73091 was 72127, checked in by [email protected], 15 years ago

JavaScriptCore: https://bugs.webkit.org/show_bug.cgi?id=49606

Reviewed by Oliver Hunt.

The bug here is that we read the prototype from the RHS argument using a regular
op_get_by_id before op_instanceof has checked that this is an object implementing
HasInstance. This incorrect behaviour gives rise to further unnecessary complexity
in the code base, since we have additional logic (implemented using the
GetByIdExceptionInfo data structures on CodeBlock) to convert not an object errors
from the get_by_id into invalid parameter errors. Having fixed this bug this code
is all redundant, since in these cases the get_by_id will never have been reached.

  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::dump):
(JSC::CodeBlock::shrinkToFit):

  • bytecode/CodeBlock.h:

(JSC::CodeBlock::addExpressionInfo):

  • bytecode/Opcode.h:
  • bytecompiler/BytecodeGenerator.cpp:

(JSC::BytecodeGenerator::BytecodeGenerator):
(JSC::BytecodeGenerator::emitCheckHasInstance):

  • bytecompiler/BytecodeGenerator.h:
  • bytecompiler/NodesCodegen.cpp:

(JSC::InstanceOfNode::emitBytecode):

  • interpreter/Interpreter.cpp:

(JSC::Interpreter::throwException):
(JSC::Interpreter::privateExecute):

  • jit/JIT.cpp:

(JSC::JIT::privateCompileMainPass):
(JSC::JIT::privateCompileSlowCases):

  • jit/JIT.h:
  • jit/JITOpcodes.cpp:

(JSC::JIT::emit_op_check_has_instance):
(JSC::JIT::emit_op_instanceof):
(JSC::JIT::emitSlow_op_check_has_instance):
(JSC::JIT::emitSlow_op_instanceof):

  • jit/JITOpcodes32_64.cpp:

(JSC::JIT::emit_op_check_has_instance):
(JSC::JIT::emit_op_instanceof):
(JSC::JIT::emitSlow_op_check_has_instance):
(JSC::JIT::emitSlow_op_instanceof):

  • jit/JITStubs.cpp:

(JSC::DEFINE_STUB_FUNCTION):

  • jit/JITStubs.h:
  • runtime/ExceptionHelpers.cpp:

(JSC::createInterruptedExecutionException):
(JSC::createTerminatedExecutionException):
(JSC::createUndefinedVariableError):
(JSC::createNotAFunctionError):
(JSC::createNotAnObjectError):

  • runtime/ExceptionHelpers.h:
  • runtime/JSGlobalData.cpp:

(JSC::JSGlobalData::JSGlobalData):

  • runtime/JSGlobalData.h:
  • runtime/JSNotAnObject.cpp:

(JSC::JSNotAnObject::toPrimitive):
(JSC::JSNotAnObject::getPrimitiveNumber):
(JSC::JSNotAnObject::toBoolean):
(JSC::JSNotAnObject::toNumber):
(JSC::JSNotAnObject::toString):
(JSC::JSNotAnObject::toObject):
(JSC::JSNotAnObject::getOwnPropertySlot):
(JSC::JSNotAnObject::getOwnPropertyDescriptor):
(JSC::JSNotAnObject::put):
(JSC::JSNotAnObject::deleteProperty):
(JSC::JSNotAnObject::getOwnPropertyNames):

  • runtime/JSNotAnObject.h:

(JSC::JSNotAnObject::JSNotAnObject):

  • runtime/JSObject.h:

(JSC::JSObject::isActivationObject):

  • runtime/JSValue.cpp:

(JSC::JSValue::toObjectSlowCase):
(JSC::JSValue::synthesizeObject):
(JSC::JSValue::synthesizePrototype):

LayoutTests: Bug 49606 - instanceof should only get the prototype property if the RHS operand implements HasInstance

Reviewed by Oliver Hunt.

  • fast/js/instanceof-XMLHttpRequest-expected.txt: Copied from LayoutTests/fast/js/instanceof-operator-expected.txt.
  • fast/js/instanceof-XMLHttpRequest.html: Copied from LayoutTests/fast/js/instanceof-operator.html.
  • fast/js/script-tests/instanceof-XMLHttpRequest.js: Copied from LayoutTests/fast/js/script-tests/instanceof-operator.js.
    • renamed existing testcase; these really test XMLHttpRequest objects, rather than the instanceof operator.
  • fast/js/instanceof-operator-expected.txt:
  • fast/js/script-tests/instanceof-operator.js:
    • added test case for: javascript: ({} instanceof { get prototype(){ alert("Error!"); } })
  • Property svn:eol-style set to native
File size: 6.3 KB
Line 
1/*
2 * Copyright (C) 1999-2001 Harri Porten ([email protected])
3 * Copyright (C) 2001 Peter Kelly ([email protected])
4 * Copyright (C) 2003, 2007, 2008 Apple Inc. All rights reserved.
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public License
17 * along with this library; see the file COPYING.LIB. If not, write to
18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 *
21 */
22
23#include "config.h"
24#include "JSValue.h"
25
26#include "BooleanConstructor.h"
27#include "BooleanPrototype.h"
28#include "Error.h"
29#include "ExceptionHelpers.h"
30#include "JSGlobalObject.h"
31#include "JSFunction.h"
32#include "JSNotAnObject.h"
33#include "NumberObject.h"
34#include <wtf/MathExtras.h>
35#include <wtf/StringExtras.h>
36
37namespace JSC {
38
39static const double D32 = 4294967296.0;
40
41// ECMA 9.4
42double JSValue::toInteger(ExecState* exec) const
43{
44 if (isInt32())
45 return asInt32();
46 double d = toNumber(exec);
47 return isnan(d) ? 0.0 : trunc(d);
48}
49
50double JSValue::toIntegerPreserveNaN(ExecState* exec) const
51{
52 if (isInt32())
53 return asInt32();
54 return trunc(toNumber(exec));
55}
56
57JSObject* JSValue::toObjectSlowCase(ExecState* exec) const
58{
59 ASSERT(!isCell());
60
61 if (isInt32() || isDouble())
62 return constructNumber(exec, asValue());
63 if (isTrue() || isFalse())
64 return constructBooleanFromImmediateBoolean(exec, asValue());
65
66 ASSERT(isUndefinedOrNull());
67 throwError(exec, createNotAnObjectError(exec, *this));
68 return new (exec) JSNotAnObject(exec);
69}
70
71JSObject* JSValue::toThisObjectSlowCase(ExecState* exec) const
72{
73 ASSERT(!isCell());
74
75 if (isInt32() || isDouble())
76 return constructNumber(exec, asValue());
77 if (isTrue() || isFalse())
78 return constructBooleanFromImmediateBoolean(exec, asValue());
79 ASSERT(isUndefinedOrNull());
80 return exec->globalThisValue();
81}
82
83JSObject* JSValue::synthesizeObject(ExecState* exec) const
84{
85 ASSERT(!isCell());
86 if (isNumber())
87 return constructNumber(exec, asValue());
88 if (isBoolean())
89 return constructBooleanFromImmediateBoolean(exec, asValue());
90
91 ASSERT(isUndefinedOrNull());
92 throwError(exec, createNotAnObjectError(exec, *this));
93 return new (exec) JSNotAnObject(exec);
94}
95
96JSObject* JSValue::synthesizePrototype(ExecState* exec) const
97{
98 ASSERT(!isCell());
99 if (isNumber())
100 return exec->lexicalGlobalObject()->numberPrototype();
101 if (isBoolean())
102 return exec->lexicalGlobalObject()->booleanPrototype();
103
104 ASSERT(isUndefinedOrNull());
105 throwError(exec, createNotAnObjectError(exec, *this));
106 return new (exec) JSNotAnObject(exec);
107}
108
109#ifndef NDEBUG
110char* JSValue::description()
111{
112 static const size_t size = 32;
113 static char description[size];
114
115 if (!*this)
116 snprintf(description, size, "<JSValue()>");
117 else if (isInt32())
118 snprintf(description, size, "Int32: %d", asInt32());
119 else if (isDouble())
120 snprintf(description, size, "Double: %lf", asDouble());
121 else if (isCell())
122 snprintf(description, size, "Cell: %p", asCell());
123 else if (isTrue())
124 snprintf(description, size, "True");
125 else if (isFalse())
126 snprintf(description, size, "False");
127 else if (isNull())
128 snprintf(description, size, "Null");
129 else if (isUndefined())
130 snprintf(description, size, "Undefined");
131 else
132 snprintf(description, size, "INVALID");
133
134 return description;
135}
136#endif
137
138// This in the ToInt32 operation is defined in section 9.5 of the ECMA-262 spec.
139// Note that this operation is identical to ToUInt32 other than to interpretation
140// of the resulting bit-pattern (as such this metod is also called to implement
141// ToUInt32).
142//
143// The operation can be descibed as round towards zero, then select the 32 least
144// bits of the resulting value in 2s-complement representation.
145int32_t toInt32(double number)
146{
147 int64_t bits = WTF::bitwise_cast<int64_t>(number);
148 int32_t exp = (static_cast<int32_t>(bits >> 52) & 0x7ff) - 0x3ff;
149
150 // If exponent < 0 there will be no bits to the left of the decimal point
151 // after rounding; if the exponent is > 83 then no bits of precision can be
152 // left in the low 32-bit range of the result (IEEE-754 doubles have 52 bits
153 // of fractional precision).
154 // Note this case handles 0, -0, and all infinte, NaN, & denormal value.
155 if (exp < 0 || exp > 83)
156 return 0;
157
158 // Select the appropriate 32-bits from the floating point mantissa. If the
159 // exponent is 52 then the bits we need to select are already aligned to the
160 // lowest bits of the 64-bit integer representation of tghe number, no need
161 // to shift. If the exponent is greater than 52 we need to shift the value
162 // left by (exp - 52), if the value is less than 52 we need to shift right
163 // accordingly.
164 int32_t result = (exp > 52)
165 ? static_cast<int32_t>(bits << (exp - 52))
166 : static_cast<int32_t>(bits >> (52 - exp));
167
168 // IEEE-754 double precision values are stored omitting an implicit 1 before
169 // the decimal point; we need to reinsert this now. We may also the shifted
170 // invalid bits into the result that are not a part of the mantissa (the sign
171 // and exponent bits from the floatingpoint representation); mask these out.
172 if (exp < 32) {
173 int32_t missingOne = 1 << exp;
174 result &= missingOne - 1;
175 result += missingOne;
176 }
177
178 // If the input value was negative (we could test either 'number' or 'bits',
179 // but testing 'bits' is likely faster) invert the result appropriately.
180 return bits < 0 ? -result : result;
181}
182
183NEVER_INLINE double nonInlineNaN()
184{
185#if OS(SYMBIAN)
186 return nanval();
187#else
188 return std::numeric_limits<double>::quiet_NaN();
189#endif
190}
191
192bool JSValue::isValidCallee()
193{
194 return asObject(asObject(asCell())->getAnonymousValue(0))->isGlobalObject();
195}
196
197} // namespace JSC
Note: See TracBrowser for help on using the repository browser.