1. 12 Nov, 2018 3 commits
    • Philip Chimento's avatar
      object: Fix build with --enable-dtrace · c5698eab
      Philip Chimento authored
      We don't build with this option very often, so this has been broken for a
      while.
      
      Closes: #196
      c5698eab
    • Marco Trevisan's avatar
      object: add reference to the property pspec we cache · 0f77ebd6
      Marco Trevisan authored
      When caching the properties param specs we get them from the class object, which
      is currently owning them, however since we're caching them we should add a
      reference to them in order to keep the ownership and clean them up properly
      when the cache is destroyed
      
      Fixes #213
      0f77ebd6
    • Philip Chimento's avatar
      object: Fix write-only properties · 9f53812a
      Philip Chimento authored
      Since the property refactor, write-only properties have not been working.
      The problem was that a getter and setter function were not defined for
      them, because is_gobject_property_name() did not consider them to be
      properties. Now, the setter function works as normal while the getter
      function just pretends a write-only property has the value of undefined.
      
      The test is marked pending until a test is added to the
      gobject-introspection test suite.
      9f53812a
  2. 10 Aug, 2018 1 commit
  3. 29 Jul, 2018 3 commits
    • Philip Chimento's avatar
      object: Define GObject properties as configurable · 6f9599b0
      Philip Chimento authored
      We copied the non-configurable flag (JSPROP_PERMANENT) from the boxed.cpp
      lazy property code, but it's more appropriate to make these properties
      configurable so that interface properties can be overridden in the class
      that implements the interface, using GObject.ParamSpec.override().
      
      Closes: #186.
      6f9599b0
    • Philip Chimento's avatar
      js: Adapt to new JSClassOps struct layout · e5019b79
      Philip Chimento authored
      The getProperty and setProperty hooks are gone.
      
      The newEnumerate hook is moved in from JSObjectOps, and so we can change
      importer.cpp to use a regular old JSClass again instead of the JS Friend
      API version which was required in order to use JSObjectOps.
      
      See: #161
      e5019b79
    • Philip Chimento's avatar
      js: Replace JS_FS with JS_FN · cda7624f
      Philip Chimento authored
      The macro simply changed its name.
      
      See: #161
      cda7624f
  4. 17 Jul, 2018 1 commit
    • Philip Chimento's avatar
      object: Resolve properties in resolve_no_info · 12ace06a
      Philip Chimento authored
      A regression from the property cache refactor caused properties like
      Gio.NetworkMonitor.network_available to disappear. This was because
      NetworkMonitor is an interface, implemented by a non-introspectable
      class, i.e. Gio.NetworkMonitor.get_default() gives you an instance of
      GNetworkMonitorBase which does not have introspection information.
      
      To fix this, we iterate through all the interfaces implemented by a
      non-introspectable type, and check if the ID to be resolved is a property
      of one of them, and define it on the prototype if so. For this we factor
      out some code into separate functions, and change resolve_no_info() to
      have a parameter specifying whether to consider only methods or both
      methods and properties.
      
      Closes: #182
      12ace06a
  5. 09 Jul, 2018 1 commit
    • Georges Basile Stavracas Neto's avatar
      object: Add GObject properties to the correct prototype · f6758a3c
      Georges Basile Stavracas Neto authored
      Whenever successfully resolving a property, GJS is mistakenly setting
      the property in the prototype of the prototype, instead of just the
      prototype. When that happens, it ends up breaking any properties of
      subclasses. Suppose the following scenario:
      
            GObject
               |________________
               |                |
        GCharsetConverter   Subclass2
               |
           Subclass1
      
      In this scenario, if 'Subclass1' accesses any possible property from
      GCharsetConverter, GJS resolves that but ends up setting this property
      in the prototype of the prototype.
      
      If 'Subclass2' then tries to subsequently access that property, the
      resolving process will accidentally call the wrong getter. This leads
      to an immediate crash.
      
      Fix that by using the correct object prototype when resolving the
      properties. A reproducer was added to the test suite in addition to
      the fix to this problem, as a protective measure.
      
      Fixes #171
      f6758a3c
  6. 30 Jun, 2018 6 commits
    • Philip Chimento's avatar
      jsapi-util-root: Use a union for mutually exclusive members · 4e7f4a53
      Philip Chimento authored
      In GjsMaybeOwned<T> the JS::Heap<T> and JS::PersistentRooted<T>* members
      are mutually exclusive. The m_rooted flag determines which one we are
      using. Therefore, we can put the two in a union to save space.
      
      The only thing we have to do is watch out when switching from one mode to
      the other. When switching to rooted, we have to be careful to call the
      destructor of JS::Heap, and when switching to unrooted we have to use
      placement-new to construct a JS::Heap in the location of the union.
      
      This reduces the size of ObjectInstance to 88 bytes on x86_64 (although
      when the GjsMaybeOwned is in rooted mode, that is, the ObjectInstance is
      in toggle ref mode and a GObject owns a reference to it, there are 32
      "hidden" bytes allocated for the PersistentRooted.)
      4e7f4a53
    • Philip Chimento's avatar
      object: Use smaller data structure for closures · 93cf31db
      Philip Chimento authored
      Some time ago, we switched from GList* to std::set to store the list of
      GClosures associated with an object. std::set was the most time-efficient
      container, but we need to optimize for space here. std::forward_list is
      comparable to GSList.
      
      This reduces ObjectInstance to 96 bytes and ObjectPrototype to 192 bytes.
      93cf31db
    • Philip Chimento's avatar
      object: Split ObjectPrototype from ObjectInstance · 4413e30d
      Philip Chimento authored
      This creates two separate classes, ObjectPrototype and ObjectInstance, so
      that we don't have to have a copy of prototype-only data in each
      ObjectInstance. This should save a lot of memory.
      
      There is one element common to both classes: a list of GClosures (for
      prototypes, these are vfuncs, and for instances, connected signals.)
      Since we can only create a JSClass with one private type, we use a common
      base class ObjectBase for that type. ObjectBase contains the list of
      closures and a means of distinguishing whether a particular ObjectBase
      pointer holds an ObjectInstance or ObjectPrototype. For this we use an
      ObjectPrototype pointer, which is null in ObjectPrototypes, and in
      ObjectInstances points to the associated prototype. (This scheme is
      similar to what we do in fundamental.cpp.)
      
      Both ObjectInstance and ObjectPrototype have an associated GObjectInfo
      and GType, but now these are stored only on the prototype.
      
      Note that we do not use RTTI and dynamic_cast<> because SpiderMonkey
      supports compiling both with and without RTTI. That's the reason for this
      unusual scheme with the ObjectPrototype pointer and the to_prototype() /
      to_instance() methods. dynamic_cast<> would certainly be cleaner and more
      readable, so that might be something to investigate in the future.
      
      This also allows moving the PropertyCache and FieldCache into
      ObjectPrototype, instead of keeping them as qdata on the GType.
      
      We now define separate memory counters for ObjectPrototype and
      ObjectInstance.
      
      On x86_64 with Clang, ObjectInstance was previously 128 bytes and is now
      112. ObjectPrototype was effectively 288 bytes (128 for ObjectInstance,
      plus 160 hidden bytes for the PropertyCache and FieldCache stored on the
      GType) and is now 208 bytes.
      
      Closes: #165
      4413e30d
    • Philip Chimento's avatar
      object: Split file into smaller logical units · 44ed1dc0
      Philip Chimento authored
      We now have object.cpp dealing only with ObjectInstance, the JSClass for
      wrapper JS objects. Two new files are created:
      
      - gobject.cpp, which is the dynamic GObject types for classes and
        interfaces created in JS code.
      
      - private.cpp, which is the private GI native module, accessible from JS
        as `imports._gi`.
      44ed1dc0
    • Philip Chimento's avatar
      object: Move some methods out of the class body · 70123645
      Philip Chimento authored
      We are going to move this class to a separate header. Methods defined in
      the class body are inlined by default, and these methods are too large
      for that.
      70123645
    • Philip Chimento's avatar
      object: Move some more stuff into ObjectInstance · cb78e8db
      Philip Chimento authored
      This is useful since we are going to be breaking up this file into some
      smaller logical units. It clarifies what belongs to ObjectInstance.
      cb78e8db
  7. 12 Jun, 2018 5 commits
    • Philip Chimento's avatar
      js: Fix return values of not-really-infallible functions · fb100c9a
      Philip Chimento authored
      While refactoring object.cpp I noticed that gjs_define_object_class()
      doesn't do proper error checking; the JSAPI functions used within it can
      throw, but it doesn't check that.
      
      Fixing this also had a cascade effect on
      gjs_object_define_static_methods() and gjs_define_param_class(), as well
      as some code in fundamental.cpp and repo.cpp.
      
      Similarly, find_vfunc_info() in object.cpp could also throw but the
      return value was never checked.
      fb100c9a
    • Philip Chimento's avatar
      object: Move imports._gi.hook_up_vfunc() to be a method · 8fb7b4e1
      Philip Chimento authored
      Since we're required to pass in a GObject prototype to
      imports._gi.hook_up_vfunc(), it makes sense to make it a method of the
      prototype. It's still only accessible by importing _gi, as we give it a
      symbol name which is exposed as imports._gi.hook_up_vfunc_symbol.
      8fb7b4e1
    • Philip Chimento's avatar
      jsapi-util: Move and rename GjsAutoParam · b056201c
      Philip Chimento authored
      We introduce a new unique_ptr variant that was previously used privately
      in object.cpp. We'll be using this in multiple files in a following
      commit.
      b056201c
    • Philip Chimento's avatar
      object: Use gjs_parse_call_args() in object methods · 74f19dcc
      Philip Chimento authored
      This cleans up some call args handling code and makes it consistent.
      It requires a small API change in gjs_parse_call_args() which should have
      had a const reference to JS::CallArgs all along.
      74f19dcc
    • Philip Chimento's avatar
      object: Use GjsAutoInfo throughout · dcce0ef9
      Philip Chimento authored
      This makes the recently refactored code safer against memory leaks.
      dcce0ef9
  8. 10 Jun, 2018 7 commits
    • Philip Chimento's avatar
      object: Check return values of for_js() and friends · 3f7bce56
      Philip Chimento authored
      ObjectInstance::for_js_nocheck() and ObjectInstance::for_js() now have
      null checks every time they are called.
      
      ObjectInstance::for_js_prototype() already had, or should have had, an
      assertion everywhere it was called, so we move the assertion into the
      function itself.
      3f7bce56
    • Philip Chimento's avatar
      object: Add debug methods · ae59d9ce
      Philip Chimento authored
      Many methods of ObjectInstance log a debug message with all the same
      information, such as the address of the GObject, the JSObject, the
      ObjectInstance, and type info. Make this uniform (and shorter) by adding
      debug methods to ObjectInstance.
      ae59d9ce
    • Philip Chimento's avatar
      object: Refactor ObjectInstance into C++ class · f311af8f
      Philip Chimento authored
      This is the first in a series of refactors that will make object.cpp
      easier to maintain and eventually save memory by using two different
      private classes for instances and prototypes.
      
      This commit changes the ObjectInstance struct to be a C++ class. (Once we
      do that it becomes quite obvious that the class should be split into an
      instance and a prototype version; it has two constructors, and many
      methods that apply only to one or the other.) The way we distinguish
      instances and prototypes is that the GObject *m_gobj member is null in
      the prototype; but again this indicates why we need the refactor, since
      occasionally m_gobj is also null during object disposal.
      
      We try to keep the diff minimal by writing the methods in the same place
      where the equivalent C code was already written. This unfortunately
      leaves the code somewhat disordered compared to the class body
      declaration.
      
      The code is now a bit more readable due to small accessor methods such as
      is_prototype(), is_custom_js_class(), etc. These methods will likely be
      inlined by the compiler.
      f311af8f
    • Philip Chimento's avatar
      object: Make GjsListLink const-correct · e3dc2f44
      Philip Chimento authored
      e3dc2f44
    • Philip Chimento's avatar
      object: Return false from throw_priv_is_null_error() · e68f61cd
      Philip Chimento authored
      For convenience, since in practice we always return false after throwing,
      we return false from this function too.
      e68f61cd
    • Philip Chimento's avatar
      object: Move GjsListLink methods out of inline · 39954a5b
      Philip Chimento authored
      We'll later convert object_instance_get_link() to a method of
      ObjectInstance, which makes the current approach of forward-declaring it
      not work.
      39954a5b
    • Philip Chimento's avatar
      object: Use g_object_new_with_properties() · dfbb2329
      Philip Chimento authored
      g_object_newv() is deprecated, and we had deprecation guards around it in
      order to silence the deprecation warning. Since we're going to refactor
      this code, it's probably time to fix this.
      
      We get rid of the awkward clear() function by moving it into the
      destructor of an AutoGValueVector class.
      
      GLib dependency is now 2.54.
      
      Closes: #104
      dfbb2329
  9. 03 Jun, 2018 1 commit
    • Philip Chimento's avatar
      object: Remove inline from proto_priv_from_js() · 451de365
      Philip Chimento authored
      The compiler is complaining about failing to inline because of the
      inline-unit-growth limit. I guess we can just remove the keyword and let
      the compiler decide here, since the inline function isn't in a header
      file.
      
      Unreviewed, pushing to fix build.
      451de365
  10. 02 Jun, 2018 1 commit
    • Philip Chimento's avatar
      object: Warn about finalized GObject in fewer cases · 8cdd6291
      Philip Chimento authored
      We want to remove this warning in cases where the subsequent code isn't
      actually trying to access the underlying GObject and therefore isn't
      going to crash. On resolve() we don't want the warning, as that only
      applies to prototype objects. On trace() we don't want it either, as that
      may legitimately be called during the GC mark phase on a JS wrapper with
      a disposed GObject.
      
      In the typecheck function, we only use the GObject for a debug assertion.
      All the other checks use the GType. We relax the assertion and only do
      the debug sanity check if the GObject is still alive. Instead of logging
      the warning here, we log the warning in gjs_g_object_from_object() which
      happens later when the GObject is actually used.
      
      We keep the warnings in property getters and setters, since those would
      access the underlying GObject, and they are now only called for names
      that really do resolve to GObject properties and fields.
      
      Closes: #24
      8cdd6291
  11. 01 Jun, 2018 2 commits
  12. 26 May, 2018 3 commits
    • Philip Chimento's avatar
      object: Remove getProperty/setProperty hooks · 729dad66
      Philip Chimento authored
      These hooks are going away in SpiderMonkey 60, so we have to do something
      different. Instead of intercepting the getProperty/setProperty
      operations, we lazily define a JS property for each GObject property or
      field accessed in the resolve hook.
      
      This uses the same native-accessor-with-private-data API used in
      gi/boxed.cpp. Two separate sets of accessors are used for properties and
      fields, which makes them a bit simpler than the previous code.
      
      One behaviour change is that we now can't distinguish whether we're
      setting a readonly property in strict mode or not. Now we always throw
      when setting a readonly property; in effect, we treat the property set as
      if it were always in strict mode. ES6 modules are always treated as
      strict mode, so this is a change that client code will have to go through
      anyway when using ES6 modules.
      
      Closes: #160
      729dad66
    • Philip Chimento's avatar
      object: Use addProperty hook to simplify toggle ref · b88ccfdd
      Philip Chimento authored
      Since the getProperty and setProperty hooks are going away in
      SpiderMonkey 60, we need to find another way to switch an object to
      toggle refs when setting custom state on it. The addProperty hook is
      called during a setProperty operation when all the resolve hooks in the
      prototype chain have failed, so it called when a new property is added to
      the object from JS code: exactly correct for our purposes.
      
      See: #160
      b88ccfdd
    • Philip Chimento's avatar
      object: Break init_g_param_from_prop() in half · e5429061
      Philip Chimento authored
      This avoids the awkward triple return state (NO_SUCH_GPROPERTY,
      VALUE_WAS_SET, SOME_ERROR_OCCURRED) by splitting init_g_param_from_prop()
      into an infallible function that looks up the GParamSpec (returning null
      if no such GObject property) and a function that initializes the
      GParameter from the GParamSpec (returning false on error).
      
      Moves the check for overridden JS properties to the place where they are
      set while not constructing, since we previously passed a bool in two
      places in the code for that.
      
      See: #160
      e5429061
  13. 21 May, 2018 5 commits
  14. 10 May, 2018 1 commit