llnode icon indicating copy to clipboard operation
llnode copied to clipboard

Should we show "Class objects" as objects?

Open mmarchini opened this issue 7 years ago • 3 comments

  • Version: llnode 1.7.0, node v8.11.1
  • Platform: OS X (10.13.4)
  • Subsystem: findjsobjects, findjsinstances, inspect

Right now if we declare a class (let's say, Lira), and we don't create an instance of that class, v8 findjsobjects will still show us that we have 1 instance of Lira. If we have a class with instances (let's say, Lero), v8 findjsobjects will show us one more instance than we actually have. Example of this behavior below.

I'm not sure how mdb_v8 handles this, but Chrome DevTools snapshots won't count classes as objects. Should we change the current behavior? Or maybe make it clearer when some object is actually a class instead of an instance?

Example:

index.js

class Lero {
  constructor() {
    this.lala = {};
  }
}

class Lira {
  constructor() {
    this.lele = {};
  }
}


const lero = new Lero();

function foo() {
  const lero2 = new Lero();
  boom();
}

foo();

llnode results

 Instances  Total Size Name
 ---------- ---------- ----
          1         24 AssertionError
          1         24 AsyncResource
          1         24 FastBuffer
          1         24 Lira
          1         24 Loader
          1         24 ModuleJob
          1         24 ModuleMap
          1         24 Performance
          1         24 PerformanceObserver
          1         24 SafeMap
          1         24 SafePromise
          1         24 SafeSet
          1         24 TextDecoder
          1         24 TextEncoder
          1         24 TickObject
          1         24 URL
          1         24 URLContext
          1         24 URLSearchParams
          1         24 WebAssembly
          1         24 console
          1         32 (Object)
          1        104 ImmediateList
          1        104 Stack
          1        112 Console
          2         48 (anonymous)
          2         48 process
          2         64 ChannelWrap
          2         64 Signal
          2        120 Resolver
          2        128 PerformanceNodeTiming
          2        136 NextTickQueue
          2        200 PerformanceObserverEntryList
          2        208 WriteStream
          2        272 Module
          2        608 ReadableState
          2        640 WritableState
          3         72 NodeError
          3         96 TTY
          3        216 Lero
          3        248 BufferList
          3        280 AsyncHook
         12        384 ContextifyScript
         14       1120 (ArrayBufferView)
         55       3520 NativeModule
        327      10464 (Array)
        642      36248 Object
       6896      53488 (String)
 ---------- ----------
       8009     109504

mmarchini avatar May 08 '18 15:05 mmarchini

Good idea, we could print them as e.g. Class: Foo.

I believe you distinguish a class constructor from a normal constructor function by looking at one of the bits (bit 3?) of its SharedFunctionInfo::compiler_hints field.

bnoordhuis avatar May 09 '18 09:05 bnoordhuis

Maybe we could look at in object properties count? Seems to be zero every time the object is a class and non-zero otherwise.

SharedFunctionInfo::compiler_hints has the IsClassConstructor bit on even on some instances (for example, if a class doesn't implement its own constructor), so it doesn't seem to be an accurate check. There's also the IsConstructor bit in Map::bit_field, but I could'nt get one example where Map::bit_field is not 00000000.

Worst case we could just look at the object's properties and consider it to be a Class if it has a constructor property...

mmarchini avatar May 10 '18 19:05 mmarchini

Maybe we could look at in object properties count? Seems to be zero every time the object is a class and non-zero otherwise.

Is that still true when you do C.x = 1 (where C is a class)?

bnoordhuis avatar May 10 '18 20:05 bnoordhuis