/* * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #pragma once #include #include #include #include #include namespace facebook { namespace hermes { namespace inspector { namespace chrome { /// Well-known object group names /** * Objects created as a result of the Debugger.paused notification (e.g. scope * objects) are placed in the "backtrace" object group. This object group is * cleared when the VM resumes. */ extern const char *BacktraceObjectGroup; /** * Objects that are created as a result of a console evaluation are placed in * the "console" object group. This object group is cleared when the client * clears the console. */ extern const char *ConsoleObjectGroup; /** * RemoteObjectsTable manages the mapping of string object ids to scope metadata * or actual JSI objects. The debugger vends these ids to the client so that the * client can perform operations on the ids (e.g. enumerate properties on the * object backed by the id). See Runtime.RemoteObjectId in the CDT docs for * more details. * * Note that object handles are not ref-counted. Suppose an object foo is mapped * to object id "objId" and is also in object group "objGroup". Then *either* of * `releaseObject("objId")` or `releaseObjectGroup("objGroup")` will remove foo * from the table. This matches the behavior of object groups in CDT. */ class RemoteObjectsTable { public: RemoteObjectsTable(); ~RemoteObjectsTable(); RemoteObjectsTable(const RemoteObjectsTable &) = delete; RemoteObjectsTable &operator=(const RemoteObjectsTable &) = delete; /** * addScope adds the provided (frameIndex, scopeIndex) mapping to the table. * If objectGroup is non-empty, then the scope object is also added to that * object group for releasing via releaseObjectGroup. Returns an object id. */ std::string addScope( std::pair frameAndScopeIndex, const std::string &objectGroup); /** * addValue adds the JSI value to the table. If objectGroup is non-empty, then * the scope object is also added to that object group for releasing via * releaseObjectGroup. Returns an object id. */ std::string addValue( ::facebook::jsi::Value value, const std::string &objectGroup); /** * Retrieves the (frameIndex, scopeIndex) associated with this object id, or * nullptr if no mapping exists. The pointer stays valid as long as you only * call const methods on this class. */ const std::pair *getScope(const std::string &objId) const; /** * Retrieves the JSI value associated with this object id, or nullptr if no * mapping exists. The pointer stays valid as long as you only call const * methods on this class. */ const ::facebook::jsi::Value *getValue(const std::string &objId) const; /** * Retrieves the object group that this object id is in, or empty string if it * isn't in an object group. The returned pointer is only guaranteed to be * valid until the next call to this class. */ std::string getObjectGroup(const std::string &objId) const; /** * Removes the scope or JSI value backed by the provided object ID from the * table. */ void releaseObject(const std::string &objId); /** * Removes all objects that are part of the provided object group from the * table. */ void releaseObjectGroup(const std::string &objectGroup); private: void releaseObject(int64_t id); int64_t scopeId_ = -1; int64_t valueId_ = 1; std::unordered_map> scopes_; std::unordered_map values_; std::unordered_map idToGroup_; std::unordered_map> groupToIds_; }; } // namespace chrome } // namespace inspector } // namespace hermes } // namespace facebook