jsobj.h 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365
  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  2. * This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #ifndef jsobj_h
  6. #define jsobj_h
  7. /*
  8. * JS object definitions.
  9. *
  10. * A JS object consists of a possibly-shared object descriptor containing
  11. * ordered property names, called the map; and a dense vector of property
  12. * values, called slots. The map/slot pointer pair is GC'ed, while the map
  13. * is reference counted and the slot vector is malloc'ed.
  14. */
  15. #include "mozilla/MemoryReporting.h"
  16. #include "gc/Barrier.h"
  17. #include "gc/Marking.h"
  18. #include "js/Conversions.h"
  19. #include "js/GCAPI.h"
  20. #include "js/GCVector.h"
  21. #include "js/HeapAPI.h"
  22. #include "vm/Shape.h"
  23. #include "vm/String.h"
  24. #include "vm/Xdr.h"
  25. namespace JS {
  26. struct ClassInfo;
  27. } // namespace JS
  28. namespace js {
  29. using PropertyDescriptorVector = JS::GCVector<JS::PropertyDescriptor>;
  30. class GCMarker;
  31. class Nursery;
  32. namespace gc {
  33. class RelocationOverlay;
  34. } // namespace gc
  35. inline JSObject*
  36. CastAsObject(GetterOp op)
  37. {
  38. return JS_FUNC_TO_DATA_PTR(JSObject*, op);
  39. }
  40. inline JSObject*
  41. CastAsObject(SetterOp op)
  42. {
  43. return JS_FUNC_TO_DATA_PTR(JSObject*, op);
  44. }
  45. inline Value
  46. CastAsObjectJsval(GetterOp op)
  47. {
  48. return ObjectOrNullValue(CastAsObject(op));
  49. }
  50. inline Value
  51. CastAsObjectJsval(SetterOp op)
  52. {
  53. return ObjectOrNullValue(CastAsObject(op));
  54. }
  55. /******************************************************************************/
  56. extern const Class IntlClass;
  57. extern const Class JSONClass;
  58. extern const Class MathClass;
  59. class GlobalObject;
  60. class NewObjectCache;
  61. enum class IntegrityLevel {
  62. Sealed,
  63. Frozen
  64. };
  65. // Forward declarations, required for later friend declarations.
  66. bool PreventExtensions(JSContext* cx, JS::HandleObject obj, JS::ObjectOpResult& result, IntegrityLevel level = IntegrityLevel::Sealed);
  67. bool SetImmutablePrototype(js::ExclusiveContext* cx, JS::HandleObject obj, bool* succeeded);
  68. } /* namespace js */
  69. /*
  70. * A JavaScript object. The members common to all objects are as follows:
  71. *
  72. * - The |group_| member stores the group of the object, which contains its
  73. * prototype object, its class and the possible types of its properties.
  74. *
  75. * Subclasses of JSObject --- mainly NativeObject and JSFunction --- add more
  76. * members. Notable among these is the object's shape, which stores flags and
  77. * some other state, and, for native objects, the layout of all its properties.
  78. * The second word of a JSObject generally stores its shape; if the second word
  79. * stores anything else, the value stored cannot be a valid Shape* pointer, so
  80. * that shape guards can be performed on objects without regard to the specific
  81. * layout in use.
  82. */
  83. class JSObject : public js::gc::Cell
  84. {
  85. protected:
  86. js::GCPtrObjectGroup group_;
  87. private:
  88. friend class js::Shape;
  89. friend class js::GCMarker;
  90. friend class js::NewObjectCache;
  91. friend class js::Nursery;
  92. friend class js::gc::RelocationOverlay;
  93. friend bool js::PreventExtensions(JSContext* cx, JS::HandleObject obj, JS::ObjectOpResult& result, js::IntegrityLevel level);
  94. friend bool js::SetImmutablePrototype(js::ExclusiveContext* cx, JS::HandleObject obj,
  95. bool* succeeded);
  96. // Make a new group to use for a singleton object.
  97. static js::ObjectGroup* makeLazyGroup(JSContext* cx, js::HandleObject obj);
  98. public:
  99. bool isNative() const {
  100. return getClass()->isNative();
  101. }
  102. const js::Class* getClass() const {
  103. return group_->clasp();
  104. }
  105. const JSClass* getJSClass() const {
  106. return Jsvalify(getClass());
  107. }
  108. bool hasClass(const js::Class* c) const {
  109. return getClass() == c;
  110. }
  111. js::LookupPropertyOp getOpsLookupProperty() const { return getClass()->getOpsLookupProperty(); }
  112. js::DefinePropertyOp getOpsDefineProperty() const { return getClass()->getOpsDefineProperty(); }
  113. js::HasPropertyOp getOpsHasProperty() const { return getClass()->getOpsHasProperty(); }
  114. js::GetPropertyOp getOpsGetProperty() const { return getClass()->getOpsGetProperty(); }
  115. js::SetPropertyOp getOpsSetProperty() const { return getClass()->getOpsSetProperty(); }
  116. js::GetOwnPropertyOp getOpsGetOwnPropertyDescriptor()
  117. const { return getClass()->getOpsGetOwnPropertyDescriptor(); }
  118. js::DeletePropertyOp getOpsDeleteProperty() const { return getClass()->getOpsDeleteProperty(); }
  119. js::GetElementsOp getOpsGetElements() const { return getClass()->getOpsGetElements(); }
  120. JSNewEnumerateOp getOpsEnumerate() const { return getClass()->getOpsEnumerate(); }
  121. JSFunToStringOp getOpsFunToString() const { return getClass()->getOpsFunToString(); }
  122. js::ObjectGroup* group() const {
  123. MOZ_ASSERT(!hasLazyGroup());
  124. return groupRaw();
  125. }
  126. js::ObjectGroup* groupRaw() const {
  127. return group_;
  128. }
  129. /*
  130. * Whether this is the only object which has its specified group. This
  131. * object will have its group constructed lazily as needed by analysis.
  132. */
  133. bool isSingleton() const {
  134. return group_->singleton();
  135. }
  136. /*
  137. * Whether the object's group has not been constructed yet. If an object
  138. * might have a lazy group, use getGroup() below, otherwise group().
  139. */
  140. bool hasLazyGroup() const {
  141. return group_->lazy();
  142. }
  143. JSCompartment* compartment() const { return group_->compartment(); }
  144. JSCompartment* maybeCompartment() const { return compartment(); }
  145. inline js::Shape* maybeShape() const;
  146. inline js::Shape* ensureShape(js::ExclusiveContext* cx);
  147. /*
  148. * Make a non-array object with the specified initial state. This method
  149. * takes ownership of any extantSlots it is passed.
  150. */
  151. static inline JSObject* create(js::ExclusiveContext* cx,
  152. js::gc::AllocKind kind,
  153. js::gc::InitialHeap heap,
  154. js::HandleShape shape,
  155. js::HandleObjectGroup group);
  156. // Set the initial slots and elements of an object. These pointers are only
  157. // valid for native objects, but during initialization are set for all
  158. // objects. For non-native objects, these must not be dynamically allocated
  159. // pointers which leak when the non-native object finishes initialization.
  160. inline void setInitialSlotsMaybeNonNative(js::HeapSlot* slots);
  161. inline void setInitialElementsMaybeNonNative(js::HeapSlot* elements);
  162. enum GenerateShape {
  163. GENERATE_NONE,
  164. GENERATE_SHAPE
  165. };
  166. static bool setFlags(js::ExclusiveContext* cx, JS::HandleObject obj, js::BaseShape::Flag flags,
  167. GenerateShape generateShape = GENERATE_NONE);
  168. inline bool hasAllFlags(js::BaseShape::Flag flags) const;
  169. /*
  170. * An object is a delegate if it is on another object's prototype or scope
  171. * chain, and therefore the delegate might be asked implicitly to get or
  172. * set a property on behalf of another object. Delegates may be accessed
  173. * directly too, as may any object, but only those objects linked after the
  174. * head of any prototype or scope chain are flagged as delegates. This
  175. * definition helps to optimize shape-based property cache invalidation
  176. * (see Purge{Scope,Proto}Chain in jsobj.cpp).
  177. */
  178. inline bool isDelegate() const;
  179. static bool setDelegate(js::ExclusiveContext* cx, JS::HandleObject obj) {
  180. return setFlags(cx, obj, js::BaseShape::DELEGATE, GENERATE_SHAPE);
  181. }
  182. inline bool isBoundFunction() const;
  183. inline bool hasSpecialEquality() const;
  184. // A "qualified" varobj is the object on which "qualified" variable
  185. // declarations (i.e., those defined with "var") are kept.
  186. //
  187. // Conceptually, when a var binding is defined, it is defined on the
  188. // innermost qualified varobj on the scope chain.
  189. //
  190. // Function scopes (CallObjects) are qualified varobjs, and there can be
  191. // no other qualified varobj that is more inner for var bindings in that
  192. // function. As such, all references to local var bindings in a function
  193. // may be statically bound to the function scope. This is subject to
  194. // further optimization. Unaliased bindings inside functions reside
  195. // entirely on the frame, not in CallObjects.
  196. //
  197. // Global scopes are also qualified varobjs. It is possible to statically
  198. // know, for a given script, that are no more inner qualified varobjs, so
  199. // free variable references can be statically bound to the global.
  200. //
  201. // Finally, there are non-syntactic qualified varobjs used by embedders
  202. // (e.g., Gecko and XPConnect), as they often wish to run scripts under a
  203. // scope that captures var bindings.
  204. inline bool isQualifiedVarObj() const;
  205. static bool setQualifiedVarObj(js::ExclusiveContext* cx, JS::HandleObject obj) {
  206. return setFlags(cx, obj, js::BaseShape::QUALIFIED_VAROBJ);
  207. }
  208. // An "unqualified" varobj is the object on which "unqualified"
  209. // assignments (i.e., bareword assignments for which the LHS does not
  210. // exist on the scope chain) are kept.
  211. inline bool isUnqualifiedVarObj() const;
  212. // Objects with an uncacheable proto can have their prototype mutated
  213. // without inducing a shape change on the object. JIT inline caches should
  214. // do an explicit group guard to guard against this. Singletons always
  215. // generate a new shape when their prototype changes, regardless of this
  216. // hasUncacheableProto flag.
  217. inline bool hasUncacheableProto() const;
  218. static bool setUncacheableProto(js::ExclusiveContext* cx, JS::HandleObject obj) {
  219. MOZ_ASSERT(obj->hasStaticPrototype(),
  220. "uncacheability as a concept is only applicable to static "
  221. "(not dynamically-computed) prototypes");
  222. return setFlags(cx, obj, js::BaseShape::UNCACHEABLE_PROTO, GENERATE_SHAPE);
  223. }
  224. /*
  225. * Whether SETLELEM was used to access this object. See also the comment near
  226. * PropertyTree::MAX_HEIGHT.
  227. */
  228. inline bool hadElementsAccess() const;
  229. static bool setHadElementsAccess(js::ExclusiveContext* cx, JS::HandleObject obj) {
  230. return setFlags(cx, obj, js::BaseShape::HAD_ELEMENTS_ACCESS);
  231. }
  232. /*
  233. * Whether there may be indexed properties on this object, excluding any in
  234. * the object's elements.
  235. */
  236. inline bool isIndexed() const;
  237. /*
  238. * If this object was instantiated with `new Ctor`, return the constructor's
  239. * display atom. Otherwise, return nullptr.
  240. */
  241. static bool constructorDisplayAtom(JSContext* cx, js::HandleObject obj,
  242. js::MutableHandleAtom name);
  243. /*
  244. * The same as constructorDisplayAtom above, however if this object has a
  245. * lazy group, nullptr is returned. This allows for use in situations that
  246. * cannot GC and where having some information, even if it is inconsistently
  247. * available, is better than no information.
  248. */
  249. JSAtom* maybeConstructorDisplayAtom() const;
  250. /* GC support. */
  251. void traceChildren(JSTracer* trc);
  252. void fixupAfterMovingGC();
  253. static const JS::TraceKind TraceKind = JS::TraceKind::Object;
  254. static const size_t MaxTagBits = 3;
  255. static bool isNullLike(const JSObject* obj) { return uintptr_t(obj) < (1 << MaxTagBits); }
  256. MOZ_ALWAYS_INLINE JS::Zone* zone() const {
  257. return group_->zone();
  258. }
  259. MOZ_ALWAYS_INLINE JS::shadow::Zone* shadowZone() const {
  260. return JS::shadow::Zone::asShadowZone(zone());
  261. }
  262. MOZ_ALWAYS_INLINE JS::Zone* zoneFromAnyThread() const {
  263. return group_->zoneFromAnyThread();
  264. }
  265. MOZ_ALWAYS_INLINE JS::shadow::Zone* shadowZoneFromAnyThread() const {
  266. return JS::shadow::Zone::asShadowZone(zoneFromAnyThread());
  267. }
  268. static MOZ_ALWAYS_INLINE void readBarrier(JSObject* obj);
  269. static MOZ_ALWAYS_INLINE void writeBarrierPre(JSObject* obj);
  270. static MOZ_ALWAYS_INLINE void writeBarrierPost(void* cellp, JSObject* prev, JSObject* next);
  271. /* Return the allocKind we would use if we were to tenure this object. */
  272. js::gc::AllocKind allocKindForTenure(const js::Nursery& nursery) const;
  273. size_t tenuredSizeOfThis() const {
  274. MOZ_ASSERT(isTenured());
  275. return js::gc::Arena::thingSize(asTenured().getAllocKind());
  276. }
  277. void addSizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf, JS::ClassInfo* info);
  278. // We can only use addSizeOfExcludingThis on tenured objects: it assumes it
  279. // can apply mallocSizeOf to bits and pieces of the object, whereas objects
  280. // in the nursery may have those bits and pieces allocated in the nursery
  281. // along with them, and are not each their own malloc blocks.
  282. size_t sizeOfIncludingThisInNursery() const;
  283. // Marks this object as having a singleton group, and leave the group lazy.
  284. // Constructs a new, unique shape for the object. This should only be
  285. // called for an object that was just created.
  286. static inline bool setSingleton(js::ExclusiveContext* cx, js::HandleObject obj);
  287. // Change an existing object to have a singleton group.
  288. static bool changeToSingleton(JSContext* cx, js::HandleObject obj);
  289. static inline js::ObjectGroup* getGroup(JSContext* cx, js::HandleObject obj);
  290. const js::GCPtrObjectGroup& groupFromGC() const {
  291. /* Direct field access for use by GC. */
  292. return group_;
  293. }
  294. /*
  295. * We permit proxies to dynamically compute their prototype if desired.
  296. * (Not all proxies will so desire: in particular, most DOM proxies can
  297. * track their prototype with a single, nullable JSObject*.) If a proxy
  298. * so desires, we store (JSObject*)0x1 in the proto field of the object's
  299. * group.
  300. *
  301. * We offer three ways to get an object's prototype:
  302. *
  303. * 1. obj->staticPrototype() returns the prototype, but it asserts if obj
  304. * is a proxy, and the proxy has opted to dynamically compute its
  305. * prototype using a getPrototype() handler.
  306. * 2. obj->taggedProto() returns a TaggedProto, which can be tested to
  307. * check if the proto is an object, nullptr, or lazily computed.
  308. * 3. js::GetPrototype(cx, obj, &proto) computes the proto of an object.
  309. * If obj is a proxy with dynamically-computed prototype, this code may
  310. * perform arbitrary behavior (allocation, GC, run JS) while computing
  311. * the proto.
  312. */
  313. js::TaggedProto taggedProto() const {
  314. return group_->proto();
  315. }
  316. bool hasTenuredProto() const;
  317. bool uninlinedIsProxy() const;
  318. JSObject* staticPrototype() const {
  319. MOZ_ASSERT(hasStaticPrototype());
  320. return taggedProto().toObjectOrNull();
  321. }
  322. // Normal objects and a subset of proxies have an uninteresting, static
  323. // (albeit perhaps mutable) [[Prototype]]. For such objects the
  324. // [[Prototype]] is just a value returned when needed for accesses, or
  325. // modified in response to requests. These objects store the
  326. // [[Prototype]] directly within |obj->group_|.
  327. bool hasStaticPrototype() const {
  328. return !hasDynamicPrototype();
  329. }
  330. // The remaining proxies have a [[Prototype]] requiring dynamic computation
  331. // for every access, going through the proxy handler {get,set}Prototype and
  332. // setImmutablePrototype methods. (Wrappers particularly use this to keep
  333. // the wrapper/wrappee [[Prototype]]s consistent.)
  334. bool hasDynamicPrototype() const {
  335. bool dynamic = taggedProto().isDynamic();
  336. MOZ_ASSERT_IF(dynamic, uninlinedIsProxy());
  337. MOZ_ASSERT_IF(dynamic, !isNative());
  338. return dynamic;
  339. }
  340. // True iff this object's [[Prototype]] is immutable. Must be called only
  341. // on objects with a static [[Prototype]]!
  342. inline bool staticPrototypeIsImmutable() const;
  343. inline void setGroup(js::ObjectGroup* group);
  344. /*
  345. * Mark an object that has been iterated over and is a singleton. We need
  346. * to recover this information in the object's type information after it
  347. * is purged on GC.
  348. */
  349. inline bool isIteratedSingleton() const;
  350. static bool setIteratedSingleton(js::ExclusiveContext* cx, JS::HandleObject obj) {
  351. return setFlags(cx, obj, js::BaseShape::ITERATED_SINGLETON);
  352. }
  353. /*
  354. * Mark an object as requiring its default 'new' type to have unknown
  355. * properties.
  356. */
  357. inline bool isNewGroupUnknown() const;
  358. static bool setNewGroupUnknown(JSContext* cx, const js::Class* clasp, JS::HandleObject obj);
  359. // Mark an object as having its 'new' script information cleared.
  360. inline bool wasNewScriptCleared() const;
  361. static bool setNewScriptCleared(js::ExclusiveContext* cx, JS::HandleObject obj) {
  362. return setFlags(cx, obj, js::BaseShape::NEW_SCRIPT_CLEARED);
  363. }
  364. /* Set a new prototype for an object with a singleton type. */
  365. static bool splicePrototype(JSContext* cx, js::HandleObject obj, const js::Class* clasp,
  366. js::Handle<js::TaggedProto> proto);
  367. /*
  368. * For bootstrapping, whether to splice a prototype for Function.prototype
  369. * or the global object.
  370. */
  371. bool shouldSplicePrototype();
  372. /*
  373. * Environment chains.
  374. *
  375. * The environment chain of an object is the link in the search path when
  376. * a script does a name lookup on an environment object. For JS internal
  377. * environment objects --- Call, LexicalEnvironment, and WithEnvironment
  378. * --- the chain is stored in the first fixed slot of the object. For
  379. * other environment objects, the chain goes directly to the global.
  380. *
  381. * In code which is not marked hasNonSyntacticScope, environment chains
  382. * can contain only syntactic environment objects (see
  383. * IsSyntacticEnvironment) with a global object at the root as the
  384. * environment of the outermost non-function script. In
  385. * hasNonSyntacticScope code, the environment of the outermost
  386. * non-function script might not be a global object, and can have a mix of
  387. * other objects above it before the global object is reached.
  388. */
  389. /*
  390. * Get the enclosing environment of an object. When called on a
  391. * non-EnvironmentObject, this will just be the global (the name
  392. * "enclosing environment" still applies in this situation because
  393. * non-EnvironmentObjects can be on the environment chain).
  394. */
  395. inline JSObject* enclosingEnvironment() const;
  396. inline js::GlobalObject& global() const;
  397. // In some rare cases the global object's compartment's global may not be
  398. // the same global object. For this reason, we need to take extra care when
  399. // tracing.
  400. //
  401. // These cases are:
  402. // 1) The off-thread parsing task uses a dummy global since it cannot
  403. // share with the actual global being used concurrently on the main
  404. // thread.
  405. // 2) A GC may occur when creating the GlobalObject, in which case the
  406. // compartment global pointer may not yet be set. In this case there is
  407. // nothing interesting to trace in the compartment.
  408. inline bool isOwnGlobal(JSTracer*) const;
  409. inline js::GlobalObject* globalForTracing(JSTracer*) const;
  410. /*
  411. * ES5 meta-object properties and operations.
  412. */
  413. public:
  414. // Indicates whether a non-proxy is extensible. Don't call on proxies!
  415. // This method really shouldn't exist -- but there are a few internal
  416. // places that want it (JITs and the like), and it'd be a pain to mark them
  417. // all as friends.
  418. inline bool nonProxyIsExtensible() const;
  419. public:
  420. /*
  421. * Iterator-specific getters and setters.
  422. */
  423. static const uint32_t ITER_CLASS_NFIXED_SLOTS = 1;
  424. /*
  425. * Back to generic stuff.
  426. */
  427. bool isCallable() const;
  428. bool isConstructor() const;
  429. JSNative callHook() const;
  430. JSNative constructHook() const;
  431. MOZ_ALWAYS_INLINE void finalize(js::FreeOp* fop);
  432. public:
  433. static bool reportReadOnly(JSContext* cx, jsid id, unsigned report = JSREPORT_ERROR);
  434. static bool reportNotConfigurable(JSContext* cx, jsid id, unsigned report = JSREPORT_ERROR);
  435. static bool reportNotExtensible(JSContext* cx, js::HandleObject obj,
  436. unsigned report = JSREPORT_ERROR);
  437. static bool nonNativeSetProperty(JSContext* cx, js::HandleObject obj, js::HandleId id,
  438. js::HandleValue v, js::HandleValue receiver,
  439. JS::ObjectOpResult& result);
  440. static bool nonNativeSetElement(JSContext* cx, js::HandleObject obj, uint32_t index,
  441. js::HandleValue v, js::HandleValue receiver,
  442. JS::ObjectOpResult& result);
  443. static bool swap(JSContext* cx, JS::HandleObject a, JS::HandleObject b);
  444. private:
  445. void fixDictionaryShapeAfterSwap();
  446. public:
  447. inline void initArrayClass();
  448. /*
  449. * In addition to the generic object interface provided by JSObject,
  450. * specific types of objects may provide additional operations. To access,
  451. * these addition operations, callers should use the pattern:
  452. *
  453. * if (obj.is<XObject>()) {
  454. * XObject& x = obj.as<XObject>();
  455. * x.foo();
  456. * }
  457. *
  458. * These XObject classes form a hierarchy. For example, for a cloned block
  459. * object, the following predicates are true: is<ClonedBlockObject>,
  460. * is<NestedScopeObject> and is<ScopeObject>. Each of these has a
  461. * respective class that derives and adds operations.
  462. *
  463. * A class XObject is defined in a vm/XObject{.h, .cpp, -inl.h} file
  464. * triplet (along with any class YObject that derives XObject).
  465. *
  466. * Note that X represents a low-level representation and does not query the
  467. * [[Class]] property of object defined by the spec (for this, see
  468. * js::GetBuiltinClass).
  469. */
  470. template <class T>
  471. inline bool is() const { return getClass() == &T::class_; }
  472. template <class T>
  473. T& as() {
  474. MOZ_ASSERT(this->is<T>());
  475. return *static_cast<T*>(this);
  476. }
  477. template <class T>
  478. const T& as() const {
  479. MOZ_ASSERT(this->is<T>());
  480. return *static_cast<const T*>(this);
  481. }
  482. #ifdef DEBUG
  483. void dump(FILE* fp) const;
  484. void dump() const;
  485. #endif
  486. /* JIT Accessors */
  487. static size_t offsetOfGroup() { return offsetof(JSObject, group_); }
  488. // Maximum size in bytes of a JSObject.
  489. static const size_t MAX_BYTE_SIZE = 4 * sizeof(void*) + 16 * sizeof(JS::Value);
  490. private:
  491. JSObject() = delete;
  492. JSObject(const JSObject& other) = delete;
  493. void operator=(const JSObject& other) = delete;
  494. };
  495. template <class U>
  496. MOZ_ALWAYS_INLINE JS::Handle<U*>
  497. js::RootedBase<JSObject*>::as() const
  498. {
  499. const JS::Rooted<JSObject*>& self = *static_cast<const JS::Rooted<JSObject*>*>(this);
  500. MOZ_ASSERT(self->is<U>());
  501. return Handle<U*>::fromMarkedLocation(reinterpret_cast<U* const*>(self.address()));
  502. }
  503. template <class U>
  504. MOZ_ALWAYS_INLINE JS::Handle<U*>
  505. js::HandleBase<JSObject*>::as() const
  506. {
  507. const JS::Handle<JSObject*>& self = *static_cast<const JS::Handle<JSObject*>*>(this);
  508. MOZ_ASSERT(self->is<U>());
  509. return Handle<U*>::fromMarkedLocation(reinterpret_cast<U* const*>(self.address()));
  510. }
  511. /*
  512. * The only sensible way to compare JSObject with == is by identity. We use
  513. * const& instead of * as a syntactic way to assert non-null. This leads to an
  514. * abundance of address-of operators to identity. Hence this overload.
  515. */
  516. static MOZ_ALWAYS_INLINE bool
  517. operator==(const JSObject& lhs, const JSObject& rhs)
  518. {
  519. return &lhs == &rhs;
  520. }
  521. static MOZ_ALWAYS_INLINE bool
  522. operator!=(const JSObject& lhs, const JSObject& rhs)
  523. {
  524. return &lhs != &rhs;
  525. }
  526. // Size of the various GC thing allocation sizes used for objects.
  527. struct JSObject_Slots0 : JSObject { void* data[3]; };
  528. struct JSObject_Slots2 : JSObject { void* data[3]; js::Value fslots[2]; };
  529. struct JSObject_Slots4 : JSObject { void* data[3]; js::Value fslots[4]; };
  530. struct JSObject_Slots8 : JSObject { void* data[3]; js::Value fslots[8]; };
  531. struct JSObject_Slots12 : JSObject { void* data[3]; js::Value fslots[12]; };
  532. struct JSObject_Slots16 : JSObject { void* data[3]; js::Value fslots[16]; };
  533. /* static */ MOZ_ALWAYS_INLINE void
  534. JSObject::readBarrier(JSObject* obj)
  535. {
  536. MOZ_ASSERT_IF(obj, !isNullLike(obj));
  537. if (obj && obj->isTenured())
  538. obj->asTenured().readBarrier(&obj->asTenured());
  539. }
  540. /* static */ MOZ_ALWAYS_INLINE void
  541. JSObject::writeBarrierPre(JSObject* obj)
  542. {
  543. MOZ_ASSERT_IF(obj, !isNullLike(obj));
  544. if (obj && obj->isTenured())
  545. obj->asTenured().writeBarrierPre(&obj->asTenured());
  546. }
  547. /* static */ MOZ_ALWAYS_INLINE void
  548. JSObject::writeBarrierPost(void* cellp, JSObject* prev, JSObject* next)
  549. {
  550. MOZ_ASSERT(cellp);
  551. MOZ_ASSERT_IF(next, !IsNullTaggedPointer(next));
  552. MOZ_ASSERT_IF(prev, !IsNullTaggedPointer(prev));
  553. // If the target needs an entry, add it.
  554. js::gc::StoreBuffer* buffer;
  555. if (next && (buffer = next->storeBuffer())) {
  556. // If we know that the prev has already inserted an entry, we can skip
  557. // doing the lookup to add the new entry. Note that we cannot safely
  558. // assert the presence of the entry because it may have been added
  559. // via a different store buffer.
  560. if (prev && prev->storeBuffer())
  561. return;
  562. buffer->putCell(static_cast<js::gc::Cell**>(cellp));
  563. return;
  564. }
  565. // Remove the prev entry if the new value does not need it.
  566. if (prev && (buffer = prev->storeBuffer()))
  567. buffer->unputCell(static_cast<js::gc::Cell**>(cellp));
  568. }
  569. namespace js {
  570. inline bool
  571. IsCallable(const Value& v)
  572. {
  573. return v.isObject() && v.toObject().isCallable();
  574. }
  575. // ES6 rev 24 (2014 April 27) 7.2.5 IsConstructor
  576. inline bool
  577. IsConstructor(const Value& v)
  578. {
  579. return v.isObject() && v.toObject().isConstructor();
  580. }
  581. } /* namespace js */
  582. class JSValueArray {
  583. public:
  584. const js::Value* array;
  585. size_t length;
  586. JSValueArray(const js::Value* v, size_t c) : array(v), length(c) {}
  587. };
  588. class ValueArray {
  589. public:
  590. js::Value* array;
  591. size_t length;
  592. ValueArray(js::Value* v, size_t c) : array(v), length(c) {}
  593. };
  594. namespace js {
  595. /*** Standard internal methods ********************************************************************
  596. *
  597. * The functions below are the fundamental operations on objects. See the
  598. * comment about "Standard internal methods" in jsapi.h.
  599. */
  600. /*
  601. * ES6 [[GetPrototypeOf]]. Get obj's prototype, storing it in protop.
  602. *
  603. * If obj is definitely not a proxy, the infallible obj->getProto() can be used
  604. * instead. See the comment on JSObject::getTaggedProto().
  605. */
  606. inline bool
  607. GetPrototype(JSContext* cx, HandleObject obj, MutableHandleObject protop);
  608. /*
  609. * ES6 [[SetPrototypeOf]]. Change obj's prototype to proto.
  610. *
  611. * Returns false on error, success of operation in *result. For example, if
  612. * obj is not extensible, its prototype is fixed. js::SetPrototype will return
  613. * true, because no exception is thrown for this; but *result will be false.
  614. */
  615. extern bool
  616. SetPrototype(JSContext* cx, HandleObject obj, HandleObject proto,
  617. ObjectOpResult& result);
  618. /* Convenience function: like the above, but throw on failure. */
  619. extern bool
  620. SetPrototype(JSContext* cx, HandleObject obj, HandleObject proto);
  621. /*
  622. * ES6 [[IsExtensible]]. Extensible objects can have new properties defined on
  623. * them. Inextensible objects can't, and their [[Prototype]] slot is fixed as
  624. * well.
  625. */
  626. inline bool
  627. IsExtensible(ExclusiveContext* cx, HandleObject obj, bool* extensible);
  628. /*
  629. * ES6 [[PreventExtensions]]. Attempt to change the [[Extensible]] bit on |obj|
  630. * to false. Indicate success or failure through the |result| outparam, or
  631. * actual error through the return value.
  632. *
  633. * The `level` argument is SM-specific. `obj` should have an integrity level of
  634. * at least `level`.
  635. */
  636. extern bool
  637. PreventExtensions(JSContext* cx, HandleObject obj, ObjectOpResult& result, IntegrityLevel level);
  638. /* Convenience function. As above, but throw on failure. */
  639. extern bool
  640. PreventExtensions(JSContext* cx, HandleObject obj, IntegrityLevel level = IntegrityLevel::Sealed);
  641. /*
  642. * ES6 [[GetOwnProperty]]. Get a description of one of obj's own properties.
  643. *
  644. * If no such property exists on obj, return true with desc.object() set to
  645. * null.
  646. */
  647. extern bool
  648. GetOwnPropertyDescriptor(JSContext* cx, HandleObject obj, HandleId id,
  649. MutableHandle<JS::PropertyDescriptor> desc);
  650. /* ES6 [[DefineOwnProperty]]. Define a property on obj. */
  651. extern bool
  652. DefineProperty(JSContext* cx, HandleObject obj, HandleId id,
  653. Handle<JS::PropertyDescriptor> desc, ObjectOpResult& result);
  654. extern bool
  655. DefineProperty(ExclusiveContext* cx, HandleObject obj, HandleId id, HandleValue value,
  656. JSGetterOp getter, JSSetterOp setter, unsigned attrs, ObjectOpResult& result);
  657. extern bool
  658. DefineProperty(ExclusiveContext* cx, HandleObject obj, PropertyName* name, HandleValue value,
  659. JSGetterOp getter, JSSetterOp setter, unsigned attrs, ObjectOpResult& result);
  660. extern bool
  661. DefineElement(ExclusiveContext* cx, HandleObject obj, uint32_t index, HandleValue value,
  662. JSGetterOp getter, JSSetterOp setter, unsigned attrs, ObjectOpResult& result);
  663. /*
  664. * When the 'result' out-param is omitted, the behavior is the same as above, except
  665. * that any failure results in a TypeError.
  666. */
  667. extern bool
  668. DefineProperty(JSContext* cx, HandleObject obj, HandleId id, Handle<JS::PropertyDescriptor> desc);
  669. extern bool
  670. DefineProperty(ExclusiveContext* cx, HandleObject obj, HandleId id, HandleValue value,
  671. JSGetterOp getter = nullptr,
  672. JSSetterOp setter = nullptr,
  673. unsigned attrs = JSPROP_ENUMERATE);
  674. extern bool
  675. DefineProperty(ExclusiveContext* cx, HandleObject obj, PropertyName* name, HandleValue value,
  676. JSGetterOp getter = nullptr,
  677. JSSetterOp setter = nullptr,
  678. unsigned attrs = JSPROP_ENUMERATE);
  679. extern bool
  680. DefineElement(ExclusiveContext* cx, HandleObject obj, uint32_t index, HandleValue value,
  681. JSGetterOp getter = nullptr,
  682. JSSetterOp setter = nullptr,
  683. unsigned attrs = JSPROP_ENUMERATE);
  684. /*
  685. * ES6 [[Has]]. Set *foundp to true if `id in obj` (that is, if obj has an own
  686. * or inherited property obj[id]), false otherwise.
  687. */
  688. inline bool
  689. HasProperty(JSContext* cx, HandleObject obj, HandleId id, bool* foundp);
  690. inline bool
  691. HasProperty(JSContext* cx, HandleObject obj, PropertyName* name, bool* foundp);
  692. /*
  693. * ES6 [[Get]]. Get the value of the property `obj[id]`, or undefined if no
  694. * such property exists.
  695. *
  696. * Typically obj == receiver; if obj != receiver then the caller is most likely
  697. * a proxy using GetProperty to finish a property get that started out as
  698. * `receiver[id]`, and we've already searched the prototype chain up to `obj`.
  699. */
  700. inline bool
  701. GetProperty(JSContext* cx, HandleObject obj, HandleValue receiver, HandleId id,
  702. MutableHandleValue vp);
  703. inline bool
  704. GetProperty(JSContext* cx, HandleObject obj, HandleValue receiver, PropertyName* name,
  705. MutableHandleValue vp)
  706. {
  707. RootedId id(cx, NameToId(name));
  708. return GetProperty(cx, obj, receiver, id, vp);
  709. }
  710. inline bool
  711. GetProperty(JSContext* cx, HandleObject obj, HandleObject receiver, HandleId id,
  712. MutableHandleValue vp)
  713. {
  714. RootedValue receiverValue(cx, ObjectValue(*receiver));
  715. return GetProperty(cx, obj, receiverValue, id, vp);
  716. }
  717. inline bool
  718. GetProperty(JSContext* cx, HandleObject obj, HandleObject receiver, PropertyName* name,
  719. MutableHandleValue vp)
  720. {
  721. RootedValue receiverValue(cx, ObjectValue(*receiver));
  722. return GetProperty(cx, obj, receiverValue, name, vp);
  723. }
  724. inline bool
  725. GetElement(JSContext* cx, HandleObject obj, HandleValue receiver, uint32_t index,
  726. MutableHandleValue vp);
  727. inline bool
  728. GetElement(JSContext* cx, HandleObject obj, HandleObject receiver, uint32_t index,
  729. MutableHandleValue vp);
  730. inline bool
  731. GetPropertyNoGC(JSContext* cx, JSObject* obj, const Value& receiver, jsid id, Value* vp);
  732. inline bool
  733. GetPropertyNoGC(JSContext* cx, JSObject* obj, JSObject* receiver, jsid id, Value* vp)
  734. {
  735. return GetPropertyNoGC(cx, obj, ObjectValue(*receiver), id, vp);
  736. }
  737. inline bool
  738. GetPropertyNoGC(JSContext* cx, JSObject* obj, const Value& receiver, PropertyName* name, Value* vp)
  739. {
  740. return GetPropertyNoGC(cx, obj, receiver, NameToId(name), vp);
  741. }
  742. inline bool
  743. GetPropertyNoGC(JSContext* cx, JSObject* obj, JSObject* receiver, PropertyName* name, Value* vp)
  744. {
  745. return GetPropertyNoGC(cx, obj, ObjectValue(*receiver), name, vp);
  746. }
  747. inline bool
  748. GetElementNoGC(JSContext* cx, JSObject* obj, const Value& receiver, uint32_t index, Value* vp);
  749. inline bool
  750. GetElementNoGC(JSContext* cx, JSObject* obj, JSObject* receiver, uint32_t index, Value* vp);
  751. /*
  752. * ES6 [[Set]]. Carry out the assignment `obj[id] = v`.
  753. *
  754. * The `receiver` argument has to do with how [[Set]] interacts with the
  755. * prototype chain and proxies. It's hard to explain and ES6 doesn't really
  756. * try. Long story short, if you just want bog-standard assignment, pass
  757. * `ObjectValue(*obj)` as receiver. Or better, use one of the signatures that
  758. * doesn't have a receiver parameter.
  759. *
  760. * Callers pass obj != receiver e.g. when a proxy is involved, obj is the
  761. * proxy's target, and the proxy is using SetProperty to finish an assignment
  762. * that started out as `receiver[id] = v`, by delegating it to obj.
  763. */
  764. inline bool
  765. SetProperty(JSContext* cx, HandleObject obj, HandleId id, HandleValue v,
  766. HandleValue receiver, ObjectOpResult& result);
  767. inline bool
  768. SetProperty(JSContext* cx, HandleObject obj, HandleId id, HandleValue v)
  769. {
  770. RootedValue receiver(cx, ObjectValue(*obj));
  771. ObjectOpResult result;
  772. return SetProperty(cx, obj, id, v, receiver, result) &&
  773. result.checkStrict(cx, obj, id);
  774. }
  775. inline bool
  776. SetProperty(JSContext* cx, HandleObject obj, PropertyName* name, HandleValue v,
  777. HandleValue receiver, ObjectOpResult& result)
  778. {
  779. RootedId id(cx, NameToId(name));
  780. return SetProperty(cx, obj, id, v, receiver, result);
  781. }
  782. inline bool
  783. SetProperty(JSContext* cx, HandleObject obj, PropertyName* name, HandleValue v)
  784. {
  785. RootedId id(cx, NameToId(name));
  786. RootedValue receiver(cx, ObjectValue(*obj));
  787. ObjectOpResult result;
  788. return SetProperty(cx, obj, id, v, receiver, result) &&
  789. result.checkStrict(cx, obj, id);
  790. }
  791. inline bool
  792. SetElement(JSContext* cx, HandleObject obj, uint32_t index, HandleValue v,
  793. HandleValue receiver, ObjectOpResult& result);
  794. /*
  795. * ES6 draft rev 31 (15 Jan 2015) 7.3.3 Put (O, P, V, Throw), except that on
  796. * success, the spec says this is supposed to return a boolean value, which we
  797. * don't bother doing.
  798. */
  799. inline bool
  800. PutProperty(JSContext* cx, HandleObject obj, HandleId id, HandleValue v, bool strict)
  801. {
  802. RootedValue receiver(cx, ObjectValue(*obj));
  803. ObjectOpResult result;
  804. return SetProperty(cx, obj, id, v, receiver, result) &&
  805. result.checkStrictErrorOrWarning(cx, obj, id, strict);
  806. }
  807. /*
  808. * ES6 [[Delete]]. Equivalent to the JS code `delete obj[id]`.
  809. */
  810. inline bool
  811. DeleteProperty(JSContext* cx, HandleObject obj, HandleId id, ObjectOpResult& result);
  812. inline bool
  813. DeleteElement(JSContext* cx, HandleObject obj, uint32_t index, ObjectOpResult& result);
  814. /*** SpiderMonkey nonstandard internal methods ***************************************************/
  815. /**
  816. * If |obj| (underneath any functionally-transparent wrapper proxies) has as
  817. * its [[GetPrototypeOf]] trap the ordinary [[GetPrototypeOf]] behavior defined
  818. * for ordinary objects, set |*isOrdinary = true| and store |obj|'s prototype
  819. * in |result|. Otherwise set |*isOrdinary = false|. In case of error, both
  820. * outparams have unspecified value.
  821. */
  822. extern bool
  823. GetPrototypeIfOrdinary(JSContext* cx, HandleObject obj, bool* isOrdinary,
  824. MutableHandleObject protop);
  825. /*
  826. * Attempt to make |obj|'s [[Prototype]] immutable, such that subsequently
  827. * trying to change it will not work. If an internal error occurred,
  828. * returns false. Otherwise, |*succeeded| is set to true iff |obj|'s
  829. * [[Prototype]] is now immutable.
  830. */
  831. extern bool
  832. SetImmutablePrototype(js::ExclusiveContext* cx, JS::HandleObject obj, bool* succeeded);
  833. extern bool
  834. GetPropertyDescriptor(JSContext* cx, HandleObject obj, HandleId id,
  835. MutableHandle<JS::PropertyDescriptor> desc);
  836. /*
  837. * Deprecated. A version of HasProperty that also returns the object on which
  838. * the property was found (but that information is unreliable for proxies), and
  839. * the Shape of the property, if native.
  840. */
  841. extern bool
  842. LookupProperty(JSContext* cx, HandleObject obj, HandleId id,
  843. MutableHandleObject objp, MutableHandleShape propp);
  844. inline bool
  845. LookupProperty(JSContext* cx, HandleObject obj, PropertyName* name,
  846. MutableHandleObject objp, MutableHandleShape propp)
  847. {
  848. RootedId id(cx, NameToId(name));
  849. return LookupProperty(cx, obj, id, objp, propp);
  850. }
  851. /* Set *result to tell whether obj has an own property with the given id. */
  852. extern bool
  853. HasOwnProperty(JSContext* cx, HandleObject obj, HandleId id, bool* result);
  854. /**
  855. * This enum is used to select whether the defined functions should be marked as
  856. * builtin native instrinsics for self-hosted code.
  857. */
  858. enum DefineAsIntrinsic {
  859. NotIntrinsic,
  860. AsIntrinsic
  861. };
  862. extern bool
  863. DefineFunctions(JSContext* cx, HandleObject obj, const JSFunctionSpec* fs,
  864. DefineAsIntrinsic intrinsic);
  865. /* ES6 draft rev 36 (2015 March 17) 7.1.1 ToPrimitive(vp[, preferredType]) */
  866. extern bool
  867. ToPrimitiveSlow(JSContext* cx, JSType hint, MutableHandleValue vp);
  868. inline bool
  869. ToPrimitive(JSContext* cx, MutableHandleValue vp)
  870. {
  871. if (vp.isPrimitive())
  872. return true;
  873. return ToPrimitiveSlow(cx, JSTYPE_VOID, vp);
  874. }
  875. inline bool
  876. ToPrimitive(JSContext* cx, JSType preferredType, MutableHandleValue vp)
  877. {
  878. if (vp.isPrimitive())
  879. return true;
  880. return ToPrimitiveSlow(cx, preferredType, vp);
  881. }
  882. /*
  883. * toString support. (This isn't called GetClassName because there's a macro in
  884. * <windows.h> with that name.)
  885. */
  886. extern const char*
  887. GetObjectClassName(JSContext* cx, HandleObject obj);
  888. /*
  889. * Return an object that may be used as `this` in place of obj. For most
  890. * objects this just returns obj.
  891. *
  892. * Some JSObjects shouldn't be exposed directly to script. This includes (at
  893. * least) WithEnvironmentObjects and Window objects. However, since both of
  894. * those can be on scope chains, we sometimes would expose those as `this` if
  895. * we were not so vigilant about calling GetThisValue where appropriate.
  896. *
  897. * See comments at ComputeImplicitThis.
  898. */
  899. Value
  900. GetThisValue(JSObject* obj);
  901. /* * */
  902. typedef JSObject* (*ClassInitializerOp)(JSContext* cx, JS::HandleObject obj);
  903. /* Fast access to builtin constructors and prototypes. */
  904. bool
  905. GetBuiltinConstructor(ExclusiveContext* cx, JSProtoKey key, MutableHandleObject objp);
  906. bool
  907. GetBuiltinPrototype(ExclusiveContext* cx, JSProtoKey key, MutableHandleObject objp);
  908. JSObject*
  909. GetBuiltinPrototypePure(GlobalObject* global, JSProtoKey protoKey);
  910. extern bool
  911. SetClassAndProto(JSContext* cx, HandleObject obj,
  912. const Class* clasp, Handle<TaggedProto> proto);
  913. extern bool
  914. IsStandardPrototype(JSObject* obj, JSProtoKey key);
  915. } /* namespace js */
  916. /*
  917. * Select Object.prototype method names shared between jsapi.cpp and jsobj.cpp.
  918. */
  919. extern const char js_watch_str[];
  920. extern const char js_unwatch_str[];
  921. extern const char js_hasOwnProperty_str[];
  922. extern const char js_isPrototypeOf_str[];
  923. extern const char js_propertyIsEnumerable_str[];
  924. #ifdef JS_OLD_GETTER_SETTER_METHODS
  925. extern const char js_defineGetter_str[];
  926. extern const char js_defineSetter_str[];
  927. extern const char js_lookupGetter_str[];
  928. extern const char js_lookupSetter_str[];
  929. #endif
  930. namespace js {
  931. inline gc::InitialHeap
  932. GetInitialHeap(NewObjectKind newKind, const Class* clasp)
  933. {
  934. if (newKind == NurseryAllocatedProxy) {
  935. MOZ_ASSERT(clasp->isProxy());
  936. MOZ_ASSERT(clasp->hasFinalize());
  937. MOZ_ASSERT(!CanNurseryAllocateFinalizedClass(clasp));
  938. return gc::DefaultHeap;
  939. }
  940. if (newKind != GenericObject)
  941. return gc::TenuredHeap;
  942. if (clasp->hasFinalize() && !CanNurseryAllocateFinalizedClass(clasp))
  943. return gc::TenuredHeap;
  944. return gc::DefaultHeap;
  945. }
  946. bool
  947. NewObjectWithTaggedProtoIsCachable(ExclusiveContext* cxArg, Handle<TaggedProto> proto,
  948. NewObjectKind newKind, const Class* clasp);
  949. // ES6 9.1.15 GetPrototypeFromConstructor.
  950. extern bool
  951. GetPrototypeFromConstructor(JSContext* cx, js::HandleObject newTarget, js::MutableHandleObject proto);
  952. extern bool
  953. GetPrototypeFromCallableConstructor(JSContext* cx, const CallArgs& args, js::MutableHandleObject proto);
  954. // Specialized call for constructing |this| with a known function callee,
  955. // and a known prototype.
  956. extern JSObject*
  957. CreateThisForFunctionWithProto(JSContext* cx, js::HandleObject callee, HandleObject newTarget,
  958. HandleObject proto, NewObjectKind newKind = GenericObject);
  959. // Specialized call for constructing |this| with a known function callee.
  960. extern JSObject*
  961. CreateThisForFunction(JSContext* cx, js::HandleObject callee, js::HandleObject newTarget,
  962. NewObjectKind newKind);
  963. // Generic call for constructing |this|.
  964. extern JSObject*
  965. CreateThis(JSContext* cx, const js::Class* clasp, js::HandleObject callee);
  966. extern JSObject*
  967. CloneObject(JSContext* cx, HandleObject obj, Handle<js::TaggedProto> proto);
  968. extern JSObject*
  969. DeepCloneObjectLiteral(JSContext* cx, HandleObject obj, NewObjectKind newKind = GenericObject);
  970. inline JSGetterOp
  971. CastAsGetterOp(JSObject* object)
  972. {
  973. return JS_DATA_TO_FUNC_PTR(JSGetterOp, object);
  974. }
  975. inline JSSetterOp
  976. CastAsSetterOp(JSObject* object)
  977. {
  978. return JS_DATA_TO_FUNC_PTR(JSSetterOp, object);
  979. }
  980. /* ES6 draft rev 32 (2015 Feb 2) 6.2.4.5 ToPropertyDescriptor(Obj) */
  981. bool
  982. ToPropertyDescriptor(JSContext* cx, HandleValue descval, bool checkAccessors,
  983. MutableHandle<JS::PropertyDescriptor> desc);
  984. /*
  985. * Throw a TypeError if desc.getterObject() or setterObject() is not
  986. * callable. This performs exactly the checks omitted by ToPropertyDescriptor
  987. * when checkAccessors is false.
  988. */
  989. bool
  990. CheckPropertyDescriptorAccessors(JSContext* cx, Handle<JS::PropertyDescriptor> desc);
  991. void
  992. CompletePropertyDescriptor(MutableHandle<JS::PropertyDescriptor> desc);
  993. /*
  994. * Read property descriptors from props, as for Object.defineProperties. See
  995. * ES5 15.2.3.7 steps 3-5.
  996. */
  997. extern bool
  998. ReadPropertyDescriptors(JSContext* cx, HandleObject props, bool checkAccessors,
  999. AutoIdVector* ids, MutableHandle<PropertyDescriptorVector> descs);
  1000. /* Read the name using a dynamic lookup on the scopeChain. */
  1001. extern bool
  1002. LookupName(JSContext* cx, HandlePropertyName name, HandleObject scopeChain,
  1003. MutableHandleObject objp, MutableHandleObject pobjp, MutableHandleShape propp);
  1004. extern bool
  1005. LookupNameNoGC(JSContext* cx, PropertyName* name, JSObject* scopeChain,
  1006. JSObject** objp, JSObject** pobjp, Shape** propp);
  1007. /*
  1008. * Like LookupName except returns the global object if 'name' is not found in
  1009. * any preceding scope.
  1010. *
  1011. * Additionally, pobjp and propp are not needed by callers so they are not
  1012. * returned.
  1013. */
  1014. extern bool
  1015. LookupNameWithGlobalDefault(JSContext* cx, HandlePropertyName name, HandleObject scopeChain,
  1016. MutableHandleObject objp);
  1017. /*
  1018. * Like LookupName except returns the unqualified var object if 'name' is not
  1019. * found in any preceding scope. Normally the unqualified var object is the
  1020. * global. If the value for the name in the looked-up scope is an
  1021. * uninitialized lexical, an UninitializedLexicalObject is returned.
  1022. *
  1023. * Additionally, pobjp is not needed by callers so it is not returned.
  1024. */
  1025. extern bool
  1026. LookupNameUnqualified(JSContext* cx, HandlePropertyName name, HandleObject scopeChain,
  1027. MutableHandleObject objp);
  1028. } // namespace js
  1029. namespace js {
  1030. extern JSObject*
  1031. FindVariableScope(JSContext* cx, JSFunction** funp);
  1032. bool
  1033. LookupPropertyPure(ExclusiveContext* cx, JSObject* obj, jsid id, JSObject** objp,
  1034. Shape** propp);
  1035. bool
  1036. LookupOwnPropertyPure(ExclusiveContext* cx, JSObject* obj, jsid id, Shape** propp,
  1037. bool* isTypedArrayOutOfRange = nullptr);
  1038. bool
  1039. GetPropertyPure(ExclusiveContext* cx, JSObject* obj, jsid id, Value* vp);
  1040. bool
  1041. GetGetterPure(ExclusiveContext* cx, JSObject* obj, jsid id, JSFunction** fp);
  1042. bool
  1043. GetOwnGetterPure(ExclusiveContext* cx, JSObject* obj, jsid id, JSFunction** fp);
  1044. bool
  1045. GetOwnNativeGetterPure(JSContext* cx, JSObject* obj, jsid id, JSNative* native);
  1046. bool
  1047. HasOwnDataPropertyPure(JSContext* cx, JSObject* obj, jsid id, bool* result);
  1048. bool
  1049. GetOwnPropertyDescriptor(JSContext* cx, HandleObject obj, HandleId id,
  1050. MutableHandle<JS::PropertyDescriptor> desc);
  1051. bool
  1052. GetOwnPropertyDescriptor(JSContext* cx, HandleObject obj, HandleId id, MutableHandleValue vp);
  1053. /*
  1054. * Like JS::FromPropertyDescriptor, but ignore desc.object() and always set vp
  1055. * to an object on success.
  1056. *
  1057. * Use JS::FromPropertyDescriptor for getOwnPropertyDescriptor, since desc.object()
  1058. * is used to indicate whether a result was found or not. Use this instead for
  1059. * defineProperty: it would be senseless to define a "missing" property.
  1060. */
  1061. extern bool
  1062. FromPropertyDescriptorToObject(JSContext* cx, Handle<JS::PropertyDescriptor> desc,
  1063. MutableHandleValue vp);
  1064. extern bool
  1065. IsDelegate(JSContext* cx, HandleObject obj, const Value& v, bool* result);
  1066. // obj is a JSObject*, but we root it immediately up front. We do it
  1067. // that way because we need a Rooted temporary in this method anyway.
  1068. extern bool
  1069. IsDelegateOfObject(JSContext* cx, HandleObject protoObj, JSObject* obj, bool* result);
  1070. /* Wrap boolean, number or string as Boolean, Number or String object. */
  1071. extern JSObject*
  1072. PrimitiveToObject(JSContext* cx, const Value& v);
  1073. } /* namespace js */
  1074. namespace js {
  1075. /* For converting stack values to objects. */
  1076. MOZ_ALWAYS_INLINE JSObject*
  1077. ToObjectFromStack(JSContext* cx, HandleValue vp)
  1078. {
  1079. if (vp.isObject())
  1080. return &vp.toObject();
  1081. return js::ToObjectSlow(cx, vp, true);
  1082. }
  1083. template<XDRMode mode>
  1084. bool
  1085. XDRObjectLiteral(XDRState<mode>* xdr, MutableHandleObject obj);
  1086. /*
  1087. * Report a TypeError: "so-and-so is not an object".
  1088. * Using NotNullObject is usually less code.
  1089. */
  1090. extern void
  1091. ReportNotObject(JSContext* cx, const Value& v);
  1092. inline JSObject*
  1093. NonNullObject(JSContext* cx, const Value& v)
  1094. {
  1095. if (v.isObject())
  1096. return &v.toObject();
  1097. ReportNotObject(cx, v);
  1098. return nullptr;
  1099. }
  1100. extern bool
  1101. GetFirstArgumentAsObject(JSContext* cx, const CallArgs& args, const char* method,
  1102. MutableHandleObject objp);
  1103. /* Helpers for throwing. These always return false. */
  1104. extern bool
  1105. Throw(JSContext* cx, jsid id, unsigned errorNumber);
  1106. extern bool
  1107. Throw(JSContext* cx, JSObject* obj, unsigned errorNumber);
  1108. /*
  1109. * ES6 rev 29 (6 Dec 2014) 7.3.13. Mark obj as non-extensible, and adjust each
  1110. * of obj's own properties' attributes appropriately: each property becomes
  1111. * non-configurable, and if level == Frozen, data properties become
  1112. * non-writable as well.
  1113. */
  1114. extern bool
  1115. SetIntegrityLevel(JSContext* cx, HandleObject obj, IntegrityLevel level);
  1116. inline bool
  1117. FreezeObject(JSContext* cx, HandleObject obj)
  1118. {
  1119. return SetIntegrityLevel(cx, obj, IntegrityLevel::Frozen);
  1120. }
  1121. /*
  1122. * ES6 rev 29 (6 Dec 2014) 7.3.14. Code shared by Object.isSealed and
  1123. * Object.isFrozen.
  1124. */
  1125. extern bool
  1126. TestIntegrityLevel(JSContext* cx, HandleObject obj, IntegrityLevel level, bool* resultp);
  1127. extern bool
  1128. SpeciesConstructor(JSContext* cx, HandleObject obj, HandleValue defaultCtor, MutableHandleValue pctor);
  1129. extern bool
  1130. SpeciesConstructor(JSContext* cx, HandleObject obj, JSProtoKey ctorKey, MutableHandleValue pctor);
  1131. extern bool
  1132. GetObjectFromIncumbentGlobal(JSContext* cx, MutableHandleObject obj);
  1133. } /* namespace js */
  1134. #endif /* jsobj_h */