1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2  * vim: set ts=8 sts=2 et sw=2 tw=80:
3  * This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #ifndef vm_PropertyResult_h
8 #define vm_PropertyResult_h
9 
10 #include "mozilla/Assertions.h"
11 
12 #include "js/HeapAPI.h"
13 #include "js/RootingAPI.h"
14 
15 #include "vm/Shape.h"
16 
17 namespace js {
18 
19 class PropertyResult {
20   enum class Kind : uint8_t {
21     NotFound,
22     NativeProperty,
23     NonNativeProperty,
24     DenseElement,
25     TypedArrayElement,
26   };
27   union {
28     // Set if kind is NativeProperty.
29     PropertyInfo propInfo_;
30     // Set if kind is DenseElement.
31     uint32_t denseIndex_;
32     // Set if kind is TypedArrayElement.
33     size_t typedArrayIndex_;
34   };
35   Kind kind_ = Kind::NotFound;
36   bool ignoreProtoChain_ = false;
37 
38  public:
39   // Note: because PropertyInfo does not have a default constructor, we can't
40   // use |= default| here.
PropertyResult()41   PropertyResult() {}
42 
43   // When a property is not found, we may additionally indicate that the
44   // prototype chain should be ignored. This occurs for:
45   //  - An out-of-range numeric property on a TypedArrayObject.
46   //  - A resolve hook recursively calling itself as it sets the property.
isNotFound()47   bool isNotFound() const { return kind_ == Kind::NotFound; }
shouldIgnoreProtoChain()48   bool shouldIgnoreProtoChain() const {
49     MOZ_ASSERT(isNotFound());
50     return ignoreProtoChain_;
51   }
52 
isFound()53   bool isFound() const { return kind_ != Kind::NotFound; }
isNonNativeProperty()54   bool isNonNativeProperty() const { return kind_ == Kind::NonNativeProperty; }
isDenseElement()55   bool isDenseElement() const { return kind_ == Kind::DenseElement; }
isTypedArrayElement()56   bool isTypedArrayElement() const { return kind_ == Kind::TypedArrayElement; }
isNativeProperty()57   bool isNativeProperty() const { return kind_ == Kind::NativeProperty; }
58 
propertyInfo()59   PropertyInfo propertyInfo() const {
60     MOZ_ASSERT(isNativeProperty());
61     return propInfo_;
62   }
63 
denseElementIndex()64   uint32_t denseElementIndex() const {
65     MOZ_ASSERT(isDenseElement());
66     return denseIndex_;
67   }
68 
typedArrayElementIndex()69   size_t typedArrayElementIndex() const {
70     MOZ_ASSERT(isTypedArrayElement());
71     return typedArrayIndex_;
72   }
73 
setNotFound()74   void setNotFound() { kind_ = Kind::NotFound; }
75 
setNativeProperty(PropertyInfo prop)76   void setNativeProperty(PropertyInfo prop) {
77     kind_ = Kind::NativeProperty;
78     propInfo_ = prop;
79   }
80 
setTypedObjectProperty()81   void setTypedObjectProperty() { kind_ = Kind::NonNativeProperty; }
setProxyProperty()82   void setProxyProperty() { kind_ = Kind::NonNativeProperty; }
83 
setDenseElement(uint32_t index)84   void setDenseElement(uint32_t index) {
85     kind_ = Kind::DenseElement;
86     denseIndex_ = index;
87   }
88 
setTypedArrayElement(size_t index)89   void setTypedArrayElement(size_t index) {
90     kind_ = Kind::TypedArrayElement;
91     typedArrayIndex_ = index;
92   }
93 
setTypedArrayOutOfRange()94   void setTypedArrayOutOfRange() {
95     kind_ = Kind::NotFound;
96     ignoreProtoChain_ = true;
97   }
setRecursiveResolve()98   void setRecursiveResolve() {
99     kind_ = Kind::NotFound;
100     ignoreProtoChain_ = true;
101   }
102 };
103 
104 }  // namespace js
105 
106 #endif /* vm_PropertyResult_h */
107