summaryrefslogtreecommitdiff
path: root/runtime/js/40_performance.js
diff options
context:
space:
mode:
authorNayeem Rahman <nayeemrmn99@gmail.com>2020-12-17 16:37:57 +0000
committerGitHub <noreply@github.com>2020-12-17 17:37:57 +0100
commitffb5f7a4e1d5d4ac488058ca3ec3c0805587fe44 (patch)
treedc7b79a699732680fa309d97e5b4c2bc5f486a4a /runtime/js/40_performance.js
parent55dc467b419b8e5897b1c832b04d63e383253d84 (diff)
refactor: Rename runtime/rt to runtime/js (#8806)
Diffstat (limited to 'runtime/js/40_performance.js')
-rw-r--r--runtime/js/40_performance.js341
1 files changed, 341 insertions, 0 deletions
diff --git a/runtime/js/40_performance.js b/runtime/js/40_performance.js
new file mode 100644
index 000000000..0a63dc704
--- /dev/null
+++ b/runtime/js/40_performance.js
@@ -0,0 +1,341 @@
+// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
+
+((window) => {
+ const { opNow } = window.__bootstrap.timers;
+ const { cloneValue, illegalConstructorKey } = window.__bootstrap.webUtil;
+
+ const customInspect = Symbol.for("Deno.customInspect");
+ let performanceEntries = [];
+
+ function findMostRecent(
+ name,
+ type,
+ ) {
+ return performanceEntries
+ .slice()
+ .reverse()
+ .find((entry) => entry.name === name && entry.entryType === type);
+ }
+
+ function convertMarkToTimestamp(mark) {
+ if (typeof mark === "string") {
+ const entry = findMostRecent(mark, "mark");
+ if (!entry) {
+ throw new SyntaxError(`Cannot find mark: "${mark}".`);
+ }
+ return entry.startTime;
+ }
+ if (mark < 0) {
+ throw new TypeError("Mark cannot be negative.");
+ }
+ return mark;
+ }
+
+ function filterByNameType(
+ name,
+ type,
+ ) {
+ return performanceEntries.filter(
+ (entry) =>
+ (name ? entry.name === name : true) &&
+ (type ? entry.entryType === type : true),
+ );
+ }
+
+ function now() {
+ return opNow();
+ }
+
+ class PerformanceEntry {
+ #name = "";
+ #entryType = "";
+ #startTime = 0;
+ #duration = 0;
+
+ get name() {
+ return this.#name;
+ }
+
+ get entryType() {
+ return this.#entryType;
+ }
+
+ get startTime() {
+ return this.#startTime;
+ }
+
+ get duration() {
+ return this.#duration;
+ }
+
+ constructor(
+ name = null,
+ entryType = null,
+ startTime = null,
+ duration = null,
+ key = null,
+ ) {
+ if (key != illegalConstructorKey) {
+ throw new TypeError("Illegal constructor.");
+ }
+ this.#name = name;
+ this.#entryType = entryType;
+ this.#startTime = startTime;
+ this.#duration = duration;
+ }
+
+ toJSON() {
+ return {
+ name: this.#name,
+ entryType: this.#entryType,
+ startTime: this.#startTime,
+ duration: this.#duration,
+ };
+ }
+
+ [customInspect]() {
+ return `${this.constructor.name} { name: "${this.name}", entryType: "${this.entryType}", startTime: ${this.startTime}, duration: ${this.duration} }`;
+ }
+ }
+
+ class PerformanceMark extends PerformanceEntry {
+ #detail = null;
+
+ get detail() {
+ return this.#detail;
+ }
+
+ get entryType() {
+ return "mark";
+ }
+
+ constructor(
+ name,
+ { detail = null, startTime = now() } = {},
+ ) {
+ super(name, "mark", startTime, 0, illegalConstructorKey);
+ if (startTime < 0) {
+ throw new TypeError("startTime cannot be negative");
+ }
+ this.#detail = cloneValue(detail);
+ }
+
+ toJSON() {
+ return {
+ name: this.name,
+ entryType: this.entryType,
+ startTime: this.startTime,
+ duration: this.duration,
+ detail: this.detail,
+ };
+ }
+
+ [customInspect]() {
+ return this.detail
+ ? `${this.constructor.name} {\n detail: ${
+ JSON.stringify(this.detail, null, 2)
+ },\n name: "${this.name}",\n entryType: "${this.entryType}",\n startTime: ${this.startTime},\n duration: ${this.duration}\n}`
+ : `${this.constructor.name} { detail: ${this.detail}, name: "${this.name}", entryType: "${this.entryType}", startTime: ${this.startTime}, duration: ${this.duration} }`;
+ }
+ }
+
+ class PerformanceMeasure extends PerformanceEntry {
+ #detail = null;
+
+ get detail() {
+ return this.#detail;
+ }
+
+ get entryType() {
+ return "measure";
+ }
+
+ constructor(
+ name,
+ startTime,
+ duration,
+ detail = null,
+ key,
+ ) {
+ if (key != illegalConstructorKey) {
+ throw new TypeError("Illegal constructor.");
+ }
+ super(name, "measure", startTime, duration, illegalConstructorKey);
+ this.#detail = cloneValue(detail);
+ }
+
+ toJSON() {
+ return {
+ name: this.name,
+ entryType: this.entryType,
+ startTime: this.startTime,
+ duration: this.duration,
+ detail: this.detail,
+ };
+ }
+
+ [customInspect]() {
+ return this.detail
+ ? `${this.constructor.name} {\n detail: ${
+ JSON.stringify(this.detail, null, 2)
+ },\n name: "${this.name}",\n entryType: "${this.entryType}",\n startTime: ${this.startTime},\n duration: ${this.duration}\n}`
+ : `${this.constructor.name} { detail: ${this.detail}, name: "${this.name}", entryType: "${this.entryType}", startTime: ${this.startTime}, duration: ${this.duration} }`;
+ }
+ }
+
+ class Performance {
+ constructor(key = null) {
+ if (key != illegalConstructorKey) {
+ throw new TypeError("Illegal constructor.");
+ }
+ }
+
+ clearMarks(markName) {
+ if (markName == null) {
+ performanceEntries = performanceEntries.filter(
+ (entry) => entry.entryType !== "mark",
+ );
+ } else {
+ performanceEntries = performanceEntries.filter(
+ (entry) => !(entry.name === markName && entry.entryType === "mark"),
+ );
+ }
+ }
+
+ clearMeasures(measureName) {
+ if (measureName == null) {
+ performanceEntries = performanceEntries.filter(
+ (entry) => entry.entryType !== "measure",
+ );
+ } else {
+ performanceEntries = performanceEntries.filter(
+ (entry) =>
+ !(entry.name === measureName && entry.entryType === "measure"),
+ );
+ }
+ }
+
+ getEntries() {
+ return filterByNameType();
+ }
+
+ getEntriesByName(
+ name,
+ type,
+ ) {
+ return filterByNameType(name, type);
+ }
+
+ getEntriesByType(type) {
+ return filterByNameType(undefined, type);
+ }
+
+ mark(
+ markName,
+ options = {},
+ ) {
+ // 3.1.1.1 If the global object is a Window object and markName uses the
+ // same name as a read only attribute in the PerformanceTiming interface,
+ // throw a SyntaxError. - not implemented
+ const entry = new PerformanceMark(markName, options);
+ // 3.1.1.7 Queue entry - not implemented
+ performanceEntries.push(entry);
+ return entry;
+ }
+
+ measure(
+ measureName,
+ startOrMeasureOptions = {},
+ endMark,
+ ) {
+ if (
+ startOrMeasureOptions && typeof startOrMeasureOptions === "object" &&
+ Object.keys(startOrMeasureOptions).length > 0
+ ) {
+ if (endMark) {
+ throw new TypeError("Options cannot be passed with endMark.");
+ }
+ if (
+ !("start" in startOrMeasureOptions) &&
+ !("end" in startOrMeasureOptions)
+ ) {
+ throw new TypeError(
+ "A start or end mark must be supplied in options.",
+ );
+ }
+ if (
+ "start" in startOrMeasureOptions &&
+ "duration" in startOrMeasureOptions &&
+ "end" in startOrMeasureOptions
+ ) {
+ throw new TypeError(
+ "Cannot specify start, end, and duration together in options.",
+ );
+ }
+ }
+ let endTime;
+ if (endMark) {
+ endTime = convertMarkToTimestamp(endMark);
+ } else if (
+ typeof startOrMeasureOptions === "object" &&
+ "end" in startOrMeasureOptions
+ ) {
+ endTime = convertMarkToTimestamp(startOrMeasureOptions.end);
+ } else if (
+ typeof startOrMeasureOptions === "object" &&
+ "start" in startOrMeasureOptions &&
+ "duration" in startOrMeasureOptions
+ ) {
+ const start = convertMarkToTimestamp(startOrMeasureOptions.start);
+ const duration = convertMarkToTimestamp(startOrMeasureOptions.duration);
+ endTime = start + duration;
+ } else {
+ endTime = now();
+ }
+ let startTime;
+ if (
+ typeof startOrMeasureOptions === "object" &&
+ "start" in startOrMeasureOptions
+ ) {
+ startTime = convertMarkToTimestamp(startOrMeasureOptions.start);
+ } else if (
+ typeof startOrMeasureOptions === "object" &&
+ "end" in startOrMeasureOptions &&
+ "duration" in startOrMeasureOptions
+ ) {
+ const end = convertMarkToTimestamp(startOrMeasureOptions.end);
+ const duration = convertMarkToTimestamp(startOrMeasureOptions.duration);
+ startTime = end - duration;
+ } else if (typeof startOrMeasureOptions === "string") {
+ startTime = convertMarkToTimestamp(startOrMeasureOptions);
+ } else {
+ startTime = 0;
+ }
+ const entry = new PerformanceMeasure(
+ measureName,
+ startTime,
+ endTime - startTime,
+ typeof startOrMeasureOptions === "object"
+ ? startOrMeasureOptions.detail ?? null
+ : null,
+ illegalConstructorKey,
+ );
+ performanceEntries.push(entry);
+ return entry;
+ }
+
+ now() {
+ return now();
+ }
+ }
+
+ const performance = new Performance(illegalConstructorKey);
+
+ window.__bootstrap.performance = {
+ PerformanceEntry,
+ PerformanceMark,
+ PerformanceMeasure,
+ Performance,
+ performance,
+ };
+})(this);