Skip to content

Commit

Permalink
perf: inline invariant function
Browse files Browse the repository at this point in the history
  • Loading branch information
jonahsnider committed May 25, 2021
1 parent 16adbd3 commit 883c483
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 62 deletions.
13 changes: 9 additions & 4 deletions src/convert-many.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import {allUnits} from './conversions';
import {convert} from './convert';
import {Units} from './types/units';
import {invariant} from './util';

const enum MatchGroups {
/** The entire match. */
Expand All @@ -28,7 +27,13 @@ export function convertMany(value: string) {
splitExpression.lastIndex = -1;
let search = splitExpression.exec(value);

invariant(search, `value did not match expression ${splitExpression}`);
if (!search) {
if (__DEV__) {
throw new Error(`value did not match expression ${splitExpression}`);
}

throw new Error();
}

return {
/**
Expand All @@ -39,8 +44,8 @@ export function convertMany(value: string) {
* @throws If the provided value was invalid
*/
to(unit: Units) {
if (__DEV__) {
invariant(unit in allUnits, `${unit} is not a valid unit`);
if (__DEV__ && !(unit in allUnits)) {
throw new Error(`${unit} is not a valid unit`);
}

let result = 0;
Expand Down
55 changes: 31 additions & 24 deletions src/convert.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {allUnits, UnitIndexes} from './conversions';
import {Converter} from './types/units';
import {invariant, UnitFamilies} from './util';
import {UnitFamilies} from './util';

type OverloadedConverter = ((
/**
Expand Down Expand Up @@ -30,14 +30,14 @@ type OverloadedConverter = ((
function _convert(quantity: number | bigint): Converter<typeof quantity> {
return {
from: (from: Exclude<keyof typeof allUnits, '__proto__'>) => {
if (__DEV__) {
invariant(from in allUnits, `${from} is not a valid unit`);
if (__DEV__ && !(from in allUnits)) {
throw new Error(`${from} is not a valid unit`);
}

return {
to: (to: typeof from) => {
if (__DEV__) {
invariant(to in allUnits, `${to} is not a valid unit`);
if (__DEV__ && !(to in allUnits)) {
throw new Error(`${to} is not a valid unit`);
}

// Inlining these references can reduce bundle size by around 5 bytes, but the performance cost from repeated object accesses is probably not worth it
Expand All @@ -47,25 +47,32 @@ function _convert(quantity: number | bigint): Converter<typeof quantity> {
if (__DEV__) {
const meters = 'm';

invariant(
!(
// prettier-ignore
// Prettier likes to wrap the condition in ( ) then move the first comment outside of that
// time -> meters
(fromUnit[UnitIndexes.Family] === UnitFamilies.Time && to === meters) ||
// meters -> time
(toUnit[UnitIndexes.Family] === UnitFamilies.Time && from === meters)
),
[
`No conversion could be found from ${from} to ${to}.`,
'Also, are you trying to convert quantities of time?',
'Because "m" is treated as meters, not minutes.',
'You probably wanted to write "123min" instead.'
].join(' ')
);
if (
// prettier-ignore
// Prettier likes to wrap the condition in ( ) then move the first comment outside of that
// time -> meters
(fromUnit[UnitIndexes.Family] === UnitFamilies.Time && to === meters) ||
// meters -> time
(toUnit[UnitIndexes.Family] === UnitFamilies.Time && from === meters)
) {
throw new Error(
[
`No conversion could be found from ${from} to ${to}.`,
'Also, are you trying to convert quantities of time?',
'Because "m" is treated as meters, not minutes.',
'You probably wanted to write "123min" instead.'
].join(' ')
);
}
}

invariant(fromUnit[UnitIndexes.Family] === toUnit[UnitIndexes.Family], `No conversion could be found from ${from} to ${to}`);
if (fromUnit[UnitIndexes.Family] !== toUnit[UnitIndexes.Family]) {
if (__DEV__) {
throw new Error(`No conversion could be found from ${from} to ${to}`);
} else {
throw new Error();
}
}

const combinedRatio = fromUnit[UnitIndexes.Ratio] / toUnit[UnitIndexes.Ratio];

Expand All @@ -78,8 +85,8 @@ function _convert(quantity: number | bigint): Converter<typeof quantity> {
// If you tried converting 30 seconds into minutes it would fail since 0.5 minutes is not an integer

bigintValue = quantity * BigInt(combinedRatio) + (BigInt(fromUnit[UnitIndexes.Difference]) - BigInt(toUnit[UnitIndexes.Difference]));
} catch (error) {
invariant(false, `Conversion for ${from} to ${to} can't be expressed as an integer`);
} catch {
throw new Error(`Conversion for ${from} to ${to} can't be expressed as an integer`);
}
} else {
bigintValue = quantity * BigInt(combinedRatio) + (BigInt(fromUnit[UnitIndexes.Difference]) - BigInt(toUnit[UnitIndexes.Difference]));
Expand Down
17 changes: 0 additions & 17 deletions src/util.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,3 @@
/**
* Throws an errror if `condition` is falsy.
* @private
* @param condition The condition to check
* @param message The error message to display in development builds
*/
export function invariant(condition: unknown, message: string): asserts condition {
if (!condition) {
if (__DEV__) {
// Message is only in development
throw new Error(message);
} else {
throw new Error();
}
}
}

/**
* Each unit has an element that identifies what family it belongs to (ex. length or time).
* You can use this to group units together when display them (ex. a dropdown GUI).
Expand Down
17 changes: 0 additions & 17 deletions test/util.test.ts

This file was deleted.

0 comments on commit 883c483

Please sign in to comment.