Skip to content

Commit

Permalink
fix: performance builtin and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
guybedford committed May 14, 2024
1 parent 3dcbdc9 commit 3bca6c6
Show file tree
Hide file tree
Showing 6 changed files with 580 additions and 1 deletion.
3 changes: 3 additions & 0 deletions builtins/web/fetch/fetch_event.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "fetch_event.h"
#include "../performance.h"
#include "../url.h"
#include "../worker-location.h"
#include "encode.h"
Expand Down Expand Up @@ -74,6 +75,8 @@ JSObject *FetchEvent::prepare_downstream_request(JSContext *cx) {

bool FetchEvent::init_incoming_request(JSContext *cx, JS::HandleObject self,
host_api::HttpIncomingRequest *req) {
builtins::web::performance::Performance::timeOrigin.emplace(
std::chrono::high_resolution_clock::now());
JS::RootedObject request(
cx, &JS::GetReservedSlot(self, static_cast<uint32_t>(Slots::Request)).toObject());

Expand Down
8 changes: 7 additions & 1 deletion builtins/web/performance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,13 @@ bool Performance::init_class(JSContext *cx, JS::HandleObject global) {
}

bool install(api::Engine *engine) {
return Performance::init_class(engine->cx(), engine->global());
if (!Performance::init_class(engine->cx(), engine->global())) {
return false;
}
if (!Performance::create(engine->cx(), engine->global())) {
return false;
}
return true;
}

} // namespace performance
Expand Down
1 change: 1 addition & 0 deletions tests/integration/handlers.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export { handler as btoa } from './btoa/btoa.js';
export { handler as performance } from './performance/performance.js';
export { handler as timers } from './timers/timers.js';
283 changes: 283 additions & 0 deletions tests/integration/performance/performance.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,283 @@
import { serveTest } from "../test-server.js";
import { assert, deepStrictEqual, strictEqual } from "../assert.js";

export const handler = serveTest(async (t) => {
t.test("Performance-interface", () => {
{
let actual = Reflect.ownKeys(Performance);
let expected = ["prototype", "length", "name"];
deepStrictEqual(actual, expected, `Reflect.ownKeys(Performance)`);
}

// Check the prototype descriptors are correct
{
let actual = Reflect.getOwnPropertyDescriptor(Performance, "prototype");
let expected = {
value: Performance.prototype,
writable: false,
enumerable: false,
configurable: false,
};
deepStrictEqual(
actual,
expected,
`Reflect.getOwnPropertyDescriptor(Performance, 'prototype')`
);
}

// Check the constructor function's defined parameter length is correct
{
let actual = Reflect.getOwnPropertyDescriptor(Performance, "length");
let expected = {
value: 0,
writable: false,
enumerable: false,
configurable: true,
};
deepStrictEqual(
actual,
expected,
`Reflect.getOwnPropertyDescriptor(Performance, 'length')`
);
}

// Check the constructor function's name is correct
{
let actual = Reflect.getOwnPropertyDescriptor(Performance, "name");
let expected = {
value: "Performance",
writable: false,
enumerable: false,
configurable: true,
};
deepStrictEqual(
actual,
expected,
`Reflect.getOwnPropertyDescriptor(Performance, 'name')`
);
}

// Check the prototype has the correct keys
{
let actual = Reflect.ownKeys(Performance.prototype);
let expected = ["constructor", "timeOrigin", "now", Symbol.toStringTag];
deepStrictEqual(
actual,
expected,
`Reflect.ownKeys(Performance.prototype)`
);
}

// Check the constructor on the prototype is correct
{
let actual = Reflect.getOwnPropertyDescriptor(
Performance.prototype,
"constructor"
);
let expected = {
writable: true,
enumerable: false,
configurable: true,
value: Performance.prototype.constructor,
};
deepStrictEqual(
actual,
expected,
`Reflect.getOwnPropertyDescriptor(Performance.prototype, 'constructor')`
);

strictEqual(
typeof Performance.prototype.constructor,
"function",
`typeof Performance.prototype.constructor`
);
}

{
let actual = Reflect.getOwnPropertyDescriptor(
Performance.prototype.constructor,
"length"
);
let expected = {
value: 0,
writable: false,
enumerable: false,
configurable: true,
};
assert(
actual,
expected,
`Reflect.getOwnPropertyDescriptor(Performance.prototype.constructor, 'length')`
);
}

{
let actual = Reflect.getOwnPropertyDescriptor(
Performance.prototype.constructor,
"name"
);
let expected = {
value: "Performance",
writable: false,
enumerable: false,
configurable: true,
};
assert(
actual,
expected,
`Reflect.getOwnPropertyDescriptor(Performance.prototype.constructor, 'name')`
);
}

// Check the Symbol.toStringTag on the prototype is correct
{
let actual = Reflect.getOwnPropertyDescriptor(
Performance.prototype,
Symbol.toStringTag
);
let expected = {
value: "performance",
writable: false,
enumerable: false,
configurable: true,
};
assert(
actual,
expected,
`Reflect.getOwnPropertyDescriptor(Performance.prototype, [Symbol.toStringTag])`
);

assert(
typeof Performance.prototype[Symbol.toStringTag],
"string",
`typeof Performance.prototype[Symbol.toStringTag]`
);
}

// Check the timeOrigin property is correct
{
let descriptors = Reflect.getOwnPropertyDescriptor(
Performance.prototype,
"timeOrigin"
);
let expected = { enumerable: true, configurable: true };
assert(
descriptors.enumerable,
true,
`Reflect.getOwnPropertyDescriptor(Performance, 'timeOrigin').enumerable`
);
assert(
descriptors.configurable,
true,
`Reflect.getOwnPropertyDescriptor(Performance, 'timeOrigin').configurable`
);
assert(
descriptors.value,
undefined,
`Reflect.getOwnPropertyDescriptor(Performance, 'timeOrigin').value`
);
assert(
descriptors.set,
undefined,
`Reflect.getOwnPropertyDescriptor(Performance, 'timeOrigin').set`
);
assert(
typeof descriptors.get,
"function",
`typeof Reflect.getOwnPropertyDescriptor(Performance, 'timeOrigin').get`
);

assert(
typeof Performance.prototype.timeOrigin,
"number",
`typeof Performance.prototype.timeOrigin`
);
}

// Check the now property is correct
{
let actual = Reflect.getOwnPropertyDescriptor(
Performance.prototype,
"now"
);
let expected = {
writable: true,
enumerable: true,
configurable: true,
value: Performance.prototype.now,
};
assert(
actual,
expected,
`Reflect.getOwnPropertyDescriptor(Performance, 'now')`
);

assert(
typeof Performance.prototype.now,
"function",
`typeof Performance.prototype.now`
);
}

{
let actual = Reflect.getOwnPropertyDescriptor(
Performance.prototype.now,
"length"
);
let expected = {
value: 0,
writable: false,
enumerable: false,
configurable: true,
};
assert(
actual,
expected,
`Reflect.getOwnPropertyDescriptor(Performance.prototype.now, 'length')`
);
}

{
let actual = Reflect.getOwnPropertyDescriptor(
Performance.prototype.now,
"name"
);
let expected = {
value: "now",
writable: false,
enumerable: false,
configurable: true,
};
assert(
actual,
expected,
`Reflect.getOwnPropertyDescriptor(Performance.prototype.now, 'name')`
);
}
});

t.test("globalThis.performance", () => {
assert(
globalThis.performance instanceof Performance,
true,
`globalThis.performance instanceof Performance`
);
});

t.test("globalThis.performance.now", () => {
throws(() => new performance.now());
assert(typeof performance.now(), "number");
assert(performance.now() > 0, true);
assert(Number.isNaN(performance.now()), false);
assert(Number.isFinite(performance.now()), true);
assert(performance.now() < Date.now(), true);
});

t.test("globalThis.performance.timeOrigin", () => {
assert(typeof performance.timeOrigin, "number");
assert(performance.timeOrigin > 0, true);
assert(Number.isNaN(performance.timeOrigin), false);
assert(Number.isFinite(performance.timeOrigin), true);
assert(performance.timeOrigin < Date.now(), true);
});
});
Loading

0 comments on commit 3bca6c6

Please sign in to comment.