Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lib: use class fields in classes that revert to symbol properties due to missing snapshot support #42361

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions lib/internal/abort_controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -291,9 +291,8 @@ function abortSignal(signal, reason) {
signal.dispatchEvent(event);
}

// TODO(joyeecheung): V8 snapshot does not support instance member
// initializers for now:
// https://bugs.chromium.org/p/v8/issues/detail?id=10704
// TODO(joyeecheung): use private fields and we'll get invalid access
// validation from V8 instead of throwing ERR_INVALID_THIS ourselves.
const kSignal = Symbol('signal');

function validateAbortController(obj) {
Expand Down
48 changes: 22 additions & 26 deletions lib/internal/event_target.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,16 +63,7 @@ const kTrustEvent = Symbol('kTrustEvent');

const { now } = require('internal/perf/utils');

// TODO(joyeecheung): V8 snapshot does not support instance member
// initializers for now:
// https://bugs.chromium.org/p/v8/issues/detail?id=10704
const kType = Symbol('type');
const kDefaultPrevented = Symbol('defaultPrevented');
const kCancelable = Symbol('cancelable');
const kTimestamp = Symbol('timestamp');
const kBubbles = Symbol('bubbles');
const kComposed = Symbol('composed');
const kPropagationStopped = Symbol('propagationStopped');

const isTrustedSet = new SafeWeakSet();
const isTrusted = ObjectGetOwnPropertyDescriptor({
Expand All @@ -86,6 +77,13 @@ function isEvent(value) {
}

class Event {
#cancelable = false;
#bubbles = false;
#composed = false;
#defaultPrevented = false;
#timestamp = now();
#propagationStopped = false;

/**
* @param {string} type
* @param {{
Expand All @@ -101,13 +99,11 @@ class Event {
allowArray: true, allowFunction: true, nullable: true,
});
const { cancelable, bubbles, composed } = { ...options };
this[kCancelable] = !!cancelable;
this[kBubbles] = !!bubbles;
this[kComposed] = !!composed;
this.#cancelable = !!cancelable;
this.#bubbles = !!bubbles;
this.#composed = !!composed;

this[kType] = `${type}`;
this[kDefaultPrevented] = false;
this[kTimestamp] = now();
this[kPropagationStopped] = false;
if (options?.[kTrustEvent]) {
isTrustedSet.add(this);
}
Expand Down Expand Up @@ -135,9 +131,9 @@ class Event {

return `${name} ${inspect({
type: this[kType],
defaultPrevented: this[kDefaultPrevented],
cancelable: this[kCancelable],
timeStamp: this[kTimestamp],
defaultPrevented: this.#defaultPrevented,
cancelable: this.#cancelable,
timeStamp: this.#timestamp,
}, opts)}`;
}

Expand All @@ -150,7 +146,7 @@ class Event {
preventDefault() {
if (!isEvent(this))
throw new ERR_INVALID_THIS('Event');
this[kDefaultPrevented] = true;
this.#defaultPrevented = true;
}

/**
Expand Down Expand Up @@ -195,7 +191,7 @@ class Event {
get cancelable() {
if (!isEvent(this))
throw new ERR_INVALID_THIS('Event');
return this[kCancelable];
return this.#cancelable;
}

/**
Expand All @@ -204,7 +200,7 @@ class Event {
get defaultPrevented() {
if (!isEvent(this))
throw new ERR_INVALID_THIS('Event');
return this[kCancelable] && this[kDefaultPrevented];
return this.#cancelable && this.#defaultPrevented;
}

/**
Expand All @@ -213,7 +209,7 @@ class Event {
get timeStamp() {
if (!isEvent(this))
throw new ERR_INVALID_THIS('Event');
return this[kTimestamp];
return this.#timestamp;
}


Expand Down Expand Up @@ -244,7 +240,7 @@ class Event {
get bubbles() {
if (!isEvent(this))
throw new ERR_INVALID_THIS('Event');
return this[kBubbles];
return this.#bubbles;
}

/**
Expand All @@ -253,7 +249,7 @@ class Event {
get composed() {
if (!isEvent(this))
throw new ERR_INVALID_THIS('Event');
return this[kComposed];
return this.#composed;
}

/**
Expand All @@ -271,7 +267,7 @@ class Event {
get cancelBubble() {
if (!isEvent(this))
throw new ERR_INVALID_THIS('Event');
return this[kPropagationStopped];
return this.#propagationStopped;
}

/**
Expand All @@ -288,7 +284,7 @@ class Event {
stopPropagation() {
if (!isEvent(this))
throw new ERR_INVALID_THIS('Event');
this[kPropagationStopped] = true;
this.#propagationStopped = true;
}

static NONE = 0;
Expand Down
75 changes: 36 additions & 39 deletions lib/internal/perf/observe.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,9 @@ const {

const { inspect } = require('util');

const kBuffer = Symbol('kBuffer');
const kCallback = Symbol('kCallback');
const kDispatch = Symbol('kDispatch');
const kEntryTypes = Symbol('kEntryTypes');
const kMaybeBuffer = Symbol('kMaybeBuffer');
const kDeprecatedFields = Symbol('kDeprecatedFields');
const kType = Symbol('kType');

const kDeprecationMessage =
'Custom PerformanceEntry accessors are deprecated. ' +
Expand Down Expand Up @@ -151,32 +147,34 @@ function maybeIncrementObserverCount(type) {
}

class PerformanceObserverEntryList {
#buffer = [];
joyeecheung marked this conversation as resolved.
Show resolved Hide resolved

constructor(entries) {
this[kBuffer] = ArrayPrototypeSort(entries, (first, second) => {
this.#buffer = ArrayPrototypeSort(entries, (first, second) => {
return first.startTime - second.startTime;
});
}

getEntries() {
return ArrayPrototypeSlice(this[kBuffer]);
return ArrayPrototypeSlice(this.#buffer);
}

getEntriesByType(type) {
type = `${type}`;
return ArrayPrototypeFilter(
this[kBuffer],
this.#buffer,
(entry) => entry.entryType === type);
}

getEntriesByName(name, type) {
name = `${name}`;
if (type != null /** not nullish */) {
return ArrayPrototypeFilter(
this[kBuffer],
this.#buffer,
(entry) => entry.name === name && entry.entryType === type);
}
return ArrayPrototypeFilter(
this[kBuffer],
this.#buffer,
(entry) => entry.name === name);
}

Expand All @@ -188,20 +186,19 @@ class PerformanceObserverEntryList {
depth: options.depth == null ? null : options.depth - 1
};

return `PerformanceObserverEntryList ${inspect(this[kBuffer], opts)}`;
return `PerformanceObserverEntryList ${inspect(this.#buffer, opts)}`;
}
}

class PerformanceObserver {
#buffer = [];
#entryTypes = new SafeSet();
#type;
#callback;

constructor(callback) {
// TODO(joyeecheung): V8 snapshot does not support instance member
// initializers for now:
// https://bugs.chromium.org/p/v8/issues/detail?id=10704
this[kBuffer] = [];
this[kEntryTypes] = new SafeSet();
this[kType] = undefined;
validateFunction(callback, 'callback');
this[kCallback] = callback;
this.#callback = callback;
}

observe(options = {}) {
Expand All @@ -219,10 +216,10 @@ class PerformanceObserver {
'options.entryTypes can not set with ' +
'options.type together');

switch (this[kType]) {
switch (this.#type) {
case undefined:
if (entryTypes !== undefined) this[kType] = kTypeMultiple;
if (type !== undefined) this[kType] = kTypeSingle;
if (entryTypes !== undefined) this.#type = kTypeMultiple;
if (type !== undefined) this.#type = kTypeSingle;
break;
case kTypeSingle:
if (entryTypes !== undefined)
Expand All @@ -238,53 +235,53 @@ class PerformanceObserver {
break;
}

if (this[kType] === kTypeMultiple) {
if (this.#type === kTypeMultiple) {
if (!ArrayIsArray(entryTypes)) {
throw new ERR_INVALID_ARG_TYPE(
'options.entryTypes',
'string[]',
entryTypes);
}
maybeDecrementObserverCounts(this[kEntryTypes]);
this[kEntryTypes].clear();
maybeDecrementObserverCounts(this.#entryTypes);
this.#entryTypes.clear();
for (let n = 0; n < entryTypes.length; n++) {
if (ArrayPrototypeIncludes(kSupportedEntryTypes, entryTypes[n])) {
this[kEntryTypes].add(entryTypes[n]);
this.#entryTypes.add(entryTypes[n]);
maybeIncrementObserverCount(entryTypes[n]);
}
}
} else {
if (!ArrayPrototypeIncludes(kSupportedEntryTypes, type))
return;
this[kEntryTypes].add(type);
this.#entryTypes.add(type);
maybeIncrementObserverCount(type);
if (buffered) {
const entries = filterBufferMapByNameAndType(undefined, type);
ArrayPrototypePushApply(this[kBuffer], entries);
ArrayPrototypePushApply(this.#buffer, entries);
kPending.add(this);
if (kPending.size)
queuePending();
}
}

if (this[kEntryTypes].size)
if (this.#entryTypes.size)
kObservers.add(this);
else
this.disconnect();
}

disconnect() {
maybeDecrementObserverCounts(this[kEntryTypes]);
maybeDecrementObserverCounts(this.#entryTypes);
kObservers.delete(this);
kPending.delete(this);
this[kBuffer] = [];
this[kEntryTypes].clear();
this[kType] = undefined;
this.#buffer = [];
this.#entryTypes.clear();
this.#type = undefined;
}

takeRecords() {
const list = this[kBuffer];
this[kBuffer] = [];
const list = this.#buffer;
this.#buffer = [];
return list;
}

Expand All @@ -293,17 +290,17 @@ class PerformanceObserver {
}

[kMaybeBuffer](entry) {
if (!this[kEntryTypes].has(entry.entryType))
if (!this.#entryTypes.has(entry.entryType))
return;
ArrayPrototypePush(this[kBuffer], entry);
ArrayPrototypePush(this.#buffer, entry);
kPending.add(this);
if (kPending.size)
queuePending();
}

[kDispatch]() {
this[kCallback](new PerformanceObserverEntryList(this.takeRecords()),
this);
this.#callback(new PerformanceObserverEntryList(this.takeRecords()),
this);
}

[kInspect](depth, options) {
Expand All @@ -317,8 +314,8 @@ class PerformanceObserver {
return `PerformanceObserver ${inspect({
connected: kObservers.has(this),
pending: kPending.has(this),
entryTypes: ArrayFrom(this[kEntryTypes]),
buffer: this[kBuffer],
entryTypes: ArrayFrom(this.#entryTypes),
buffer: this.#buffer,
}, opts)}`;
}
}
Expand Down