Skip to content
This repository has been archived by the owner on Apr 3, 2024. It is now read-only.

Commit

Permalink
fix: support new stable object ID query method
Browse files Browse the repository at this point in the history
  • Loading branch information
kjin committed Sep 17, 2018
1 parent bd6359b commit e19be5f
Showing 1 changed file with 50 additions and 12 deletions.
62 changes: 50 additions & 12 deletions src/agent/state/inspector-state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,14 @@ const NATIVE_PROPERTY_MESSAGE_INDEX = 1;
const GETTER_MESSAGE_INDEX = 2;
const ARG_LOCAL_LIMIT_MESSAGE_INDEX = 3;

const STABLE_OBJECT_ID_PROPERTY = '[[StableObjectId]]';
const NO_STABLE_OBJECT_ID = -1;

interface RawVariableTableEntry {
objectId?: string;
description?: string;
stableObjectId: number;
}

/**
* Checks that the provided expressions will not have side effects and
Expand Down Expand Up @@ -79,7 +87,7 @@ class StateResolver {
private totalSize: number;
private messageTable: stackdriver.Variable[];
private resolvedVariableTable: stackdriver.Variable[];
private rawVariableTable: Array<inspector.Runtime.RemoteObject|null>;
private rawVariableTable: Array<RawVariableTableEntry|null>;

/**
* @param {Array<!Object>} callFrames
Expand Down Expand Up @@ -462,7 +470,35 @@ class StateResolver {
return type === 'function';
}

/**
* Gets the stable object ID for a given object, or NO_STABLE_OBJECT_ID
* if it can't be obtained.
* @param remoteObject The object whose stable object ID should be retrieved.
*/
private getStableObjectId(remoteObject: inspector.Runtime.RemoteObject):
number {
if (remoteObject.objectId === undefined) {
// Unexpected... but since this is required to obtain the stable object
// ID, return a value that specifies that it is not available.
return NO_STABLE_OBJECT_ID;
}
const properties =
this.v8Inspector.getProperties({objectId: remoteObject.objectId});
if (properties.error || !properties.response ||
!properties.response.internalProperties) {
return NO_STABLE_OBJECT_ID;
}
const stableObjectIdProperty = properties.response.internalProperties.find(
property => property.name === STABLE_OBJECT_ID_PROPERTY);
if (!stableObjectIdProperty || !stableObjectIdProperty.value ||
stableObjectIdProperty.value.value === undefined) {
return NO_STABLE_OBJECT_ID;
}
return stableObjectIdProperty.value.value;
}

getVariableIndex_(value: inspector.Runtime.RemoteObject): number {
const stableObjectId = this.getStableObjectId(value);
let idx = this.rawVariableTable.findIndex(rawVar => {
if (rawVar) {
// stableObjectId was introduced in Node 10.x.y as a more reliable way
Expand All @@ -472,11 +508,8 @@ class StateResolver {
// TODO(kjin): When stableObjectId is added to Node 10:
// 1. Fill in x.y with the appropriate versions.
// 2. Update DT Node inspector versions, and remove `any` casts here.
if (value.hasOwnProperty('stableObjectId')) {
// tslint:disable:no-any
return (rawVar as any).stableObjectId ===
(value as any).stableObjectId;
// tslint:enable:no-any
if (stableObjectId !== NO_STABLE_OBJECT_ID) {
return rawVar.stableObjectId === stableObjectId;
} else {
// Fall back to using objectId for old versions of Node. Note that
// this will cause large data payloads for objects with circular
Expand All @@ -494,21 +527,26 @@ class StateResolver {
}

storeObjectToVariableTable_(obj: inspector.Runtime.RemoteObject): number {
const stableObjectId = this.getStableObjectId(obj);
const idx = this.rawVariableTable.length;
this.rawVariableTable[idx] = obj;
this.rawVariableTable[idx] = {
objectId: obj.objectId,
description: obj.description,
stableObjectId
};
return idx;
}

/**
* Responsible for recursively resolving the properties on a
* provided remote object.
*/
resolveRemoteObject_(
object: inspector.Runtime.RemoteObject,
isEvaluated: boolean): stackdriver.Variable {
resolveRemoteObject_(object: RawVariableTableEntry, isEvaluated: boolean):
stackdriver.Variable {
const maxProps = this.config.capture.maxProperties;
const result =
this.v8Inspector.getProperties({objectId: object.objectId as string});
// TS: ! is OK since getProperties will populate result.error in the absence
// of an object ID.
const result = this.v8Inspector.getProperties({objectId: object.objectId!});
const members: Array<{}> = [];
if (result.error || !result.response) {
members.push({
Expand Down

0 comments on commit e19be5f

Please sign in to comment.