KJS

value.h
1 /*
2  * This file is part of the KDE libraries
3  * Copyright (C) 1999-2001 Harri Porten ([email protected])
4  * Copyright (C) 2001 Peter Kelly ([email protected])
5  * Copyright (C) 2003, 2004, 2005, 2007 Apple Inc. All rights reserved.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public License
18  * along with this library; see the file COPYING.LIB. If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  *
22  */
23 
24 #ifndef KJS_VALUE_H
25 #define KJS_VALUE_H
26 
27 #include "JSImmediate.h"
28 #include "ustring.h"
29 #include "collector.h"
30 #include <wtf/Noncopyable.h>
31 #include <stddef.h> // for size_t
32 
33 #ifndef NDEBUG // protection against problems if committing with KJS_VERBOSE on
34 
35 // Uncomment this to enable very verbose output from KJS
36 //#define KJS_VERBOSE
37 // Uncomment this to debug memory allocation and garbage collection
38 //#define KJS_DEBUG_MEM
39 
40 #endif
41 
42 namespace KJS
43 {
44 
45 struct ClassInfo;
46 class ExecState;
47 class JSObject;
48 class JSCell;
49 
58 class KJS_EXPORT JSValue : Noncopyable
59 {
60  friend class JSCell; // so it can derive from this class
61  friend class Collector; // so it can call asCell()
62 
63 private:
64  JSValue();
65  virtual ~JSValue();
66 
67 public:
68  // Querying the type.
69  JSType type() const;
70  bool isUndefined() const;
71  bool isNull() const;
72  bool isUndefinedOrNull() const;
73  bool isBoolean() const;
74  bool isNumber() const;
75  bool isString() const;
76  bool isObject() const;
77  bool isObject(const ClassInfo *) const;
78 
79  // Extracting the value.
80  bool getBoolean(bool &) const;
81  bool getBoolean() const; // false if not a boolean
82  bool getNumber(double &) const;
83  double getNumber() const; // NaN if not a number
84  bool getString(UString &) const;
85  UString getString() const; // null string if not a string
86  JSObject *getObject(); // NULL if not an object
87  const JSObject *getObject() const; // NULL if not an object
88 
89  // Extracting integer values.
90  bool getUInt32(uint32_t &) const;
91  bool getTruncatedInt32(int32_t &) const;
92  bool getTruncatedUInt32(uint32_t &) const;
93 
94  JSValue *getByIndex(ExecState *exec, unsigned propertyName) const;
95 
96  // Basic conversions.
97  JSValue *toPrimitive(ExecState *exec, JSType preferredType = UnspecifiedType) const;
98  bool getPrimitiveNumber(ExecState *exec, double &number, JSValue *&value);
99 
100  bool toBoolean(ExecState *exec) const;
101  double toNumber(ExecState *exec) const;
102  JSValue *toJSNumber(ExecState *) const; // Fast path for when you expect that the value is an immediate number.
103  UString toString(ExecState *exec) const;
104  JSObject *toObject(ExecState *exec) const;
105 
106  // Integer conversions.
107  double toInteger(ExecState *) const;
108  double toIntegerPreserveNaN(ExecState *) const;
109  int32_t toInt32(ExecState *) const;
110  int32_t toInt32(ExecState *, bool &ok) const;
111  uint32_t toUInt32(ExecState *) const;
112  uint32_t toUInt32(ExecState *, bool &ok) const;
113  uint16_t toUInt16(ExecState *exec) const;
114 
115  // These are identical logic to above, and faster than jsNumber(number)->toInt32(exec)
116  static int32_t toInt32(double);
117  static int32_t toUInt32(double);
118 
119  // Floating point conversions.
120  float toFloat(ExecState *) const;
121 
122  // Object-level properties...
123 
132  bool implementsCall() const;
133 
134  // Garbage collection.
135  void mark();
136  bool marked() const;
137 
138  static int32_t toInt32SlowCase(double, bool &ok);
139  static uint32_t toUInt32SlowCase(double, bool &ok);
140 
141 private:
142  int32_t toInt32SlowCase(ExecState *, bool &ok) const;
143  uint32_t toUInt32SlowCase(ExecState *, bool &ok) const;
144 
145  // Implementation details.
146  JSCell *asCell();
147  const JSCell *asCell() const;
148 
149  // emulate Q_DISABLE_COPY to avoid msvc linker errors
150 #if !defined(_MSC_VER) || !defined(MAKE_KJS_LIB)
151  // Give a compile time error if we try to copy one of these.
152  JSValue(const JSValue &);
153  JSValue &operator=(const JSValue &);
154 #endif
155 };
156 
157 class KJS_EXPORT JSCell : public JSValue
158 {
159  friend class Collector;
160  friend class NumberImp;
161  friend class StringImp;
162  friend class JSObject;
163  friend class GetterSetterImp;
164 private:
165  explicit JSCell();
166  virtual ~JSCell();
167 public:
168  // Querying the type.
169  virtual JSType type() const = 0;
170  bool isNumber() const;
171  bool isString() const;
172  bool isObject() const;
173  bool isObject(const ClassInfo *) const;
174 
175  // Extracting the value.
176  bool getNumber(double &) const;
177  double getNumber() const; // NaN if not a number
178  bool getString(UString &) const;
179  UString getString() const; // null string if not a string
180  JSObject *getObject(); // NULL if not an object
181  const JSObject *getObject() const; // NULL if not an object
182 
183  // Extracting integer values.
184  virtual bool getUInt32(uint32_t &) const;
185  virtual bool getTruncatedInt32(int32_t &) const;
186  virtual bool getTruncatedUInt32(uint32_t &) const;
187 
188  // Basic conversions.
189  virtual JSValue *toPrimitive(ExecState *exec, JSType preferredType = UnspecifiedType) const = 0;
190  virtual bool getPrimitiveNumber(ExecState *exec, double &number, JSValue *&value) = 0;
191  virtual bool toBoolean(ExecState *exec) const = 0;
192  virtual double toNumber(ExecState *exec) const = 0;
193  virtual UString toString(ExecState *exec) const = 0;
194  virtual JSObject *toObject(ExecState *exec) const = 0;
195 
196  // Higher-level (object-like) properties:
197  virtual bool implementsCall() const;
198 
199  // Garbage collection.
200  void *operator new(size_t);
201  virtual void mark();
202  bool marked() const;
203 };
204 
205 KJS_EXPORT JSValue *jsNumberCell(double);
206 
207 KJS_EXPORT JSCell *jsString(); // returns empty string
208 KJS_EXPORT JSCell *jsString(const UString &); // returns empty string if passed null string
209 KJS_EXPORT JSCell *jsString(const char * = ""); // returns empty string if passed 0
210 KJS_EXPORT JSCell *jsString(const char *s, int len);
211 
212 // should be used for strings that are owned by an object that will
213 // likely outlive the JSValue this makes, such as the parse tree or a
214 // DOM object that contains a UString
215 JSCell *jsOwnedString(const UString &);
216 
217 inline JSValue *jsUndefined()
218 {
219  return JSImmediate::undefinedImmediate();
220 }
221 
222 inline JSValue *jsNull()
223 {
224  return JSImmediate::nullImmediate();
225 }
226 
227 inline JSValue *jsNaN()
228 {
229  static const union {
230  uint64_t bits;
231  double d;
232  } nan = { 0x7ff80000ULL << 32 };
233  return jsNumberCell(nan.d);
234 }
235 
236 inline JSValue *jsBoolean(bool b)
237 {
238  return b ? JSImmediate::trueImmediate() : JSImmediate::falseImmediate();
239 }
240 
241 ALWAYS_INLINE JSValue *jsNumber(double d)
242 {
243  JSValue *v = JSImmediate::from(d);
244  return v ? v : jsNumberCell(d);
245 }
246 
247 ALWAYS_INLINE JSValue *jsNumber(int i)
248 {
249  JSValue *v = JSImmediate::from(i);
250  return v ? v : jsNumberCell(i);
251 }
252 
253 ALWAYS_INLINE JSValue *jsNumber(unsigned i)
254 {
255  JSValue *v = JSImmediate::from(i);
256  return v ? v : jsNumberCell(i);
257 }
258 
259 ALWAYS_INLINE JSValue *jsNumber(long i)
260 {
261  JSValue *v = JSImmediate::from(i);
262  return v ? v : jsNumberCell(i);
263 }
264 
265 ALWAYS_INLINE JSValue *jsNumber(unsigned long i)
266 {
267  JSValue *v = JSImmediate::from(i);
268  return v ? v : jsNumberCell(i);
269 }
270 
271 ALWAYS_INLINE JSValue *jsNumber(long long i)
272 {
273  JSValue *v = JSImmediate::from(i);
274  return v ? v : jsNumberCell(static_cast<double>(i));
275 }
276 
277 ALWAYS_INLINE JSValue *jsNumber(unsigned long long i)
278 {
279  JSValue *v = JSImmediate::from(i);
280  return v ? v : jsNumberCell(static_cast<double>(i));
281 }
282 
283 ALWAYS_INLINE JSValue *jsNumberFromAnd(ExecState *exec, JSValue *v1, JSValue *v2)
284 {
285  if (JSImmediate::areBothImmediateNumbers(v1, v2)) {
286  return JSImmediate::andImmediateNumbers(v1, v2);
287  }
288  return jsNumber(v1->toInt32(exec) & v2->toInt32(exec));
289 }
290 
291 inline JSValue::JSValue()
292 {
293 }
294 
295 inline JSValue::~JSValue()
296 {
297 }
298 
299 inline JSCell::JSCell()
300 {
301 }
302 
303 inline JSCell::~JSCell()
304 {
305 }
306 
307 inline bool JSCell::isNumber() const
308 {
309  return type() == NumberType;
310 }
311 
312 inline bool JSCell::isString() const
313 {
314  return type() == StringType;
315 }
316 
317 inline bool JSCell::isObject() const
318 {
319  return type() == ObjectType;
320 }
321 
322 inline bool JSCell::marked() const
323 {
324  return Collector::isCellMarked(this);
325 }
326 
327 inline void JSCell::mark()
328 {
329  return Collector::markCell(this);
330 }
331 
332 ALWAYS_INLINE JSCell *JSValue::asCell()
333 {
334  ASSERT(!JSImmediate::isImmediate(this));
335  return static_cast<JSCell *>(this);
336 }
337 
338 ALWAYS_INLINE const JSCell *JSValue::asCell() const
339 {
340  ASSERT(!JSImmediate::isImmediate(this));
341  return static_cast<const JSCell *>(this);
342 }
343 
344 inline bool JSValue::isUndefined() const
345 {
346  return this == jsUndefined();
347 }
348 
349 inline bool JSValue::isNull() const
350 {
351  return this == jsNull();
352 }
353 
354 inline bool JSValue::isUndefinedOrNull() const
355 {
356  return JSImmediate::isUndefinedOrNull(this);
357 }
358 
359 inline bool JSValue::isBoolean() const
360 {
361  return JSImmediate::isBoolean(this);
362 }
363 
364 inline bool JSValue::isNumber() const
365 {
366  return JSImmediate::isNumber(this) ||
367  (!JSImmediate::isImmediate(this) && asCell()->isNumber());
368 }
369 
370 inline bool JSValue::isString() const
371 {
372  return !JSImmediate::isImmediate(this) && asCell()->isString();
373 }
374 
375 inline bool JSValue::isObject() const
376 {
377  return !JSImmediate::isImmediate(this) && asCell()->isObject();
378 }
379 
380 inline bool JSValue::getBoolean(bool &v) const
381 {
382  if (JSImmediate::isBoolean(this)) {
383  v = JSImmediate::toBoolean(this);
384  return true;
385  }
386 
387  return false;
388 }
389 
390 inline bool JSValue::getBoolean() const
391 {
392  return JSImmediate::isBoolean(this) ? JSImmediate::toBoolean(this) : false;
393 }
394 
395 inline bool JSValue::getNumber(double &v) const
396 {
397  if (JSImmediate::isImmediate(this)) {
398  return JSImmediate::getNumber(this, v);
399  }
400  return asCell()->getNumber(v);
401 }
402 
403 inline double JSValue::getNumber() const
404 {
405  return JSImmediate::isImmediate(this) ? JSImmediate::getNumber(this) : asCell()->getNumber();
406 }
407 
408 inline bool JSValue::getString(UString &s) const
409 {
410  return !JSImmediate::isImmediate(this) && asCell()->getString(s);
411 }
412 
413 inline UString JSValue::getString() const
414 {
415  return JSImmediate::isImmediate(this) ? UString() : asCell()->getString();
416 }
417 
418 inline JSObject *JSValue::getObject()
419 {
420  return JSImmediate::isImmediate(this) ? nullptr : asCell()->getObject();
421 }
422 
423 inline const JSObject *JSValue::getObject() const
424 {
425  return JSImmediate::isImmediate(this) ? nullptr : asCell()->getObject();
426 }
427 
428 ALWAYS_INLINE bool JSValue::getUInt32(uint32_t &v) const
429 {
430  return JSImmediate::isImmediate(this) ? JSImmediate::getUInt32(this, v) : asCell()->getUInt32(v);
431 }
432 
433 ALWAYS_INLINE bool JSValue::getTruncatedInt32(int32_t &v) const
434 {
435  return JSImmediate::isImmediate(this) ? JSImmediate::getTruncatedInt32(this, v) : asCell()->getTruncatedInt32(v);
436 }
437 
438 inline bool JSValue::getTruncatedUInt32(uint32_t &v) const
439 {
440  return JSImmediate::isImmediate(this) ? JSImmediate::getTruncatedUInt32(this, v) : asCell()->getTruncatedUInt32(v);
441 }
442 
443 inline void JSValue::mark()
444 {
445  ASSERT(!JSImmediate::isImmediate(this)); // callers should check !marked() before calling mark()
446  asCell()->mark();
447 }
448 
449 inline bool JSValue::marked() const
450 {
451  return JSImmediate::isImmediate(this) || asCell()->marked();
452 }
453 
454 inline JSType JSValue::type() const
455 {
456  return JSImmediate::isImmediate(this) ? JSImmediate::type(this) : asCell()->type();
457 }
458 
459 inline JSValue *JSValue::toPrimitive(ExecState *exec, JSType preferredType) const
460 {
461  return JSImmediate::isImmediate(this) ? const_cast<JSValue *>(this) : asCell()->toPrimitive(exec, preferredType);
462 }
463 
464 inline bool JSValue::getPrimitiveNumber(ExecState *exec, double &number, JSValue *&value)
465 {
466  if (JSImmediate::isImmediate(this)) {
467  number = JSImmediate::toDouble(this);
468  value = this;
469  return true;
470  }
471  return asCell()->getPrimitiveNumber(exec, number, value);
472 }
473 
474 inline bool JSValue::toBoolean(ExecState *exec) const
475 {
476  return JSImmediate::isImmediate(this) ? JSImmediate::toBoolean(this) : asCell()->toBoolean(exec);
477 }
478 
479 ALWAYS_INLINE double JSValue::toNumber(ExecState *exec) const
480 {
481  return JSImmediate::isImmediate(this) ? JSImmediate::toDouble(this) : asCell()->toNumber(exec);
482 }
483 
484 ALWAYS_INLINE JSValue *JSValue::toJSNumber(ExecState *exec) const
485 {
486  return JSImmediate::isNumber(this) ? const_cast<JSValue *>(this) : jsNumber(this->toNumber(exec));
487 }
488 
489 inline UString JSValue::toString(ExecState *exec) const
490 {
491  return JSImmediate::isImmediate(this) ? JSImmediate::toString(this) : asCell()->toString(exec);
492 }
493 
494 inline JSObject *JSValue::toObject(ExecState *exec) const
495 {
496  return JSImmediate::isImmediate(this) ? JSImmediate::toObject(this, exec) : asCell()->toObject(exec);
497 }
498 
499 ALWAYS_INLINE int32_t JSValue::toInt32(ExecState *exec) const
500 {
501  int32_t i;
502  if (getTruncatedInt32(i)) {
503  return i;
504  }
505  bool ok;
506  return toInt32SlowCase(exec, ok);
507 }
508 
509 inline uint32_t JSValue::toUInt32(ExecState *exec) const
510 {
511  uint32_t i;
512  if (getTruncatedUInt32(i)) {
513  return i;
514  }
515  bool ok;
516  return toUInt32SlowCase(exec, ok);
517 }
518 
519 inline int32_t JSValue::toInt32(double val)
520 {
521  if (!(val >= -2147483648.0 && val < 2147483648.0)) {
522  bool ignored;
523  return toInt32SlowCase(val, ignored);
524  }
525  return static_cast<int32_t>(val);
526 }
527 
528 inline int32_t JSValue::toUInt32(double val)
529 {
530  if (!(val >= 0.0 && val < 4294967296.0)) {
531  bool ignored;
532  return toUInt32SlowCase(val, ignored);
533  }
534  return static_cast<uint32_t>(val);
535 }
536 
537 inline int32_t JSValue::toInt32(ExecState *exec, bool &ok) const
538 {
539  int32_t i;
540  if (getTruncatedInt32(i)) {
541  ok = true;
542  return i;
543  }
544  return toInt32SlowCase(exec, ok);
545 }
546 
547 inline uint32_t JSValue::toUInt32(ExecState *exec, bool &ok) const
548 {
549  uint32_t i;
550  if (getTruncatedUInt32(i)) {
551  ok = true;
552  return i;
553  }
554  return toUInt32SlowCase(exec, ok);
555 }
556 
557 inline bool JSValue::implementsCall() const
558 {
559  if (JSImmediate::isImmediate(this)) {
560  return false; // immediate values are never calleable.
561  } else {
562  return asCell()->implementsCall();
563  }
564 }
565 
566 } // namespace
567 
568 #endif // KJS_VALUE_H
Unicode string class.
Definition: ustring.h:153
JSValue is the base type for all primitives (Undefined, Null, Boolean, String, Number) and objects in...
Definition: value.h:58
ObjectType
Class Information.
Definition: object.h:48
bool implementsCall() const
Whether or not the value implements the call() method.
Definition: value.h:557
Garbage collector.
Definition: collector.h:42
Represents the current state of script execution.
Definition: ExecState.h:53
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Tue Jul 7 2020 22:58:20 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.