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

Clean up dedupe to better match other entrypoints #360

Merged
merged 1 commit into from
Jan 8, 2024
Merged
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
139 changes: 65 additions & 74 deletions dedupe.js
Original file line number Diff line number Diff line change
@@ -1,94 +1,85 @@
const classNames = (function () {
// don't inherit from Object so we can skip hasOwnProperty check later
// http://stackoverflow.com/questions/15518328/creating-js-object-with-object-createnull#answer-21079232
function StorageObject() {}
StorageObject.prototype = Object.create(null);

function _parseArray (resultSet, array) {
const length = array.length;

for (let i = 0; i < length; ++i) {
_parse(resultSet, array[i]);
}
// Don't inherit from Object so we can skip hasOwnProperty check later.
function StorageObject () {}
StorageObject.prototype = Object.create(null);

export default function classNames () {
// Don't leak arguments.
// https://github.com/petkaantonov/bluebird/wiki/Optimization-killers#32-leaking-arguments
const length = arguments.length;
const args = Array(length);

for (let i = 0; i < length; i++) {
args[i] = arguments[i];
}

const hasOwn = {}.hasOwnProperty;

function _parseNumber (resultSet, num) {
resultSet[num] = true;
}
const classSet = new StorageObject();
appendArray(classSet, args);

function _parseObject (resultSet, object) {
if (object.toString !== Object.prototype.toString && !object.toString.toString().includes('[native code]')) {
resultSet[object.toString()] = true;
return;
}
const list = [];

for (const k in object) {
if (hasOwn.call(object, k)) {
// set value to false instead of deleting it to avoid changing object structure
// https://www.smashingmagazine.com/2012/11/writing-fast-memory-efficient-javascript/#de-referencing-misconceptions
resultSet[k] = !!object[k];
}
for (const k in classSet) {
if (classSet[k]) {
list.push(k);
}
}

const SPACE = /\s+/;
function _parseString (resultSet, str) {
const array = str.split(SPACE);
const length = array.length;

for (let i = 0; i < length; ++i) {
resultSet[array[i]] = true;
}
return list.join(' ');
}

function appendValue (classSet, arg) {
if (!arg) return;
const argType = typeof arg;

if (argType === 'string') {
appendString(classSet, arg);
} else if (Array.isArray(arg)) {
appendArray(classSet, arg);
} else if (argType === 'object') {
appendObject(classSet, arg);
} else if (argType === 'number') {
appendNumber(classSet, arg);
}
}

function _parse (resultSet, arg) {
if (!arg) return;
const argType = typeof arg;
const SPACE = /\s+/;

// 'foo bar'
if (argType === 'string') {
_parseString(resultSet, arg);
function appendString (classSet, str) {
const array = str.split(SPACE);
const length = array.length;

// ['foo', 'bar', ...]
} else if (Array.isArray(arg)) {
_parseArray(resultSet, arg);
for (let i = 0; i < length; i++) {
classSet[array[i]] = true;
}
}

// { 'foo': true, ... }
} else if (argType === 'object') {
_parseObject(resultSet, arg);
function appendArray (classSet, array) {
const length = array.length;

// '130'
} else if (argType === 'number') {
_parseNumber(resultSet, arg);
}
for (let i = 0; i < length; i++) {
appendValue(classSet, array[i]);
}
}

function _classNames () {
// don't leak arguments
// https://github.com/petkaantonov/bluebird/wiki/Optimization-killers#32-leaking-arguments
const length = arguments.length;
const args = Array(length);
for (let i = 0; i < length; i++) {
args[i] = arguments[i];
}
function appendNumber (classSet, num) {
classSet[num] = true;
}

const classSet = new StorageObject();
_parseArray(classSet, args);
const hasOwn = {}.hasOwnProperty;

const list = [];
function appendObject (classSet, object) {
if (
object.toString !== Object.prototype.toString &&
!object.toString.toString().includes('[native code]')
) {
classSet[object.toString()] = true;
return;
}

for (const k in classSet) {
if (classSet[k]) {
list.push(k)
}
for (const k in object) {
if (hasOwn.call(object, k)) {
// Set value to false instead of deleting it to avoid changing object structure.
// https://www.smashingmagazine.com/2012/11/writing-fast-memory-efficient-javascript/#de-referencing-misconceptions
classSet[k] = !!object[k];
}

return list.join(' ');
}

return _classNames;
})();

export default classNames;
}