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

isEmpty and other ways to avoid toString() calls #137

Merged
merged 1 commit into from Mar 19, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions index.d.ts
Expand Up @@ -48,6 +48,7 @@ export class Bundle {
trim(charType?: string): Bundle;
trimStart(charType?: string): Bundle;
trimEnd(charType?: string): Bundle;
isEmpty(): boolean;
}

export type ExclusionRange = [ number, number ];
Expand Down Expand Up @@ -90,6 +91,9 @@ export default class MagicString {
remove(start: number, end: number): MagicString;
slice(start: number, end: number): string;
snip(start: number, end: number): MagicString;
trim(): MagicString;

isEmpty(): boolean;

original: string;
}
27 changes: 13 additions & 14 deletions src/Bundle.js
Expand Up @@ -195,8 +195,7 @@ export default class Bundle {
indentStart //: trailingNewline || /\r?\n$/.test( separator ) //true///\r?\n/.test( separator )
});

// TODO this is a very slow way to determine this
trailingNewline = source.content.toString().slice(0, -1) === '\n';
trailingNewline = source.content.lastChar() === '\n';
});

if (this.intro) {
Expand Down Expand Up @@ -228,6 +227,14 @@ export default class Bundle {
return this.intro + body;
}

isEmpty () {
if (this.intro.length && this.intro.trim())
return false;
if (this.sources.some(source => !source.content.isEmpty()))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we avoid some in favor of simple for .. of loops? They also get transpiled into for loops by Buble here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh, I didn't know Buble would handle the transpilation here.

Could do, although at this order of loop it probably isn't much of a difference.

return false;
return true;
}

trimLines() {
return this.trim('[\\r\\n]');
}
Expand All @@ -245,15 +252,11 @@ export default class Bundle {
let i = 0;

do {
source = this.sources[i];

source = this.sources[i++];
if (!source) {
break;
}

source.content.trimStart(charType);
i += 1;
} while (source.content.toString() === ''); // TODO faster way to determine non-empty source?
} while (!source.content.trimStartAborted(charType));
}

return this;
Expand All @@ -266,16 +269,12 @@ export default class Bundle {
let i = this.sources.length - 1;

do {
source = this.sources[i];

source = this.sources[i--];
if (!source) {
this.intro = this.intro.replace(rx, '');
break;
}

source.content.trimEnd(charType);
i -= 1;
} while (source.content.toString() === ''); // TODO faster way to determine non-empty source?
} while (!source.content.trimEndAborted(charType));

return this;
}
Expand Down
47 changes: 40 additions & 7 deletions src/MagicString.js
Expand Up @@ -459,6 +459,19 @@ export default class MagicString {
return this;
}

lastChar() {
let chunk = this.lastChunk;
do {
if (chunk.outro.length)
return chunk.outro[chunk.outro.length - 1];
if (chunk.content.length)
return chunk.content[chunk.content.length - 1];
if (chunk.intro.length)
return chunk.intro[chunk.intro.length - 1];
} while (chunk = chunk.previous);
return '';
}

slice(start = 0, end = this.original.length) {
while (start < 0) start += this.original.length;
while (end < 0) end += this.original.length;
Expand Down Expand Up @@ -568,6 +581,17 @@ export default class MagicString {
return str + this.outro;
}

isEmpty() {
let chunk = this.firstChunk;
do {
if (chunk.intro.length && chunk.intro.trim() ||
chunk.content.length && chunk.content.trim() ||
chunk.outro.length && chunk.outro.trim())
return false;
} while (chunk = chunk.next);
return true;
}

trimLines() {
return this.trim('[\\r\\n]');
}
Expand All @@ -576,11 +600,11 @@ export default class MagicString {
return this.trimStart(charType).trimEnd(charType);
}

trimEnd(charType) {
trimEndAborted(charType) {
const rx = new RegExp((charType || '\\s') + '+$');

this.outro = this.outro.replace(rx, '');
if (this.outro.length) return this;
if (this.outro.length) return true;

let chunk = this.lastChunk;

Expand All @@ -599,18 +623,22 @@ export default class MagicString {
this.byEnd[chunk.next.end] = chunk.next;
}

if (aborted) return this;
if (aborted) return true;
chunk = chunk.previous;
} while (chunk);

return this;
return false;
}

trimStart(charType) {
trimEnd(charType) {
this.trimEndAborted(charType);
return this;
}
trimStartAborted(charType) {
const rx = new RegExp('^' + (charType || '\\s') + '+');

this.intro = this.intro.replace(rx, '');
if (this.intro.length) return this;
if (this.intro.length) return true;

let chunk = this.firstChunk;

Expand All @@ -627,10 +655,15 @@ export default class MagicString {
this.byEnd[chunk.next.end] = chunk.next;
}

if (aborted) return this;
if (aborted) return true;
chunk = chunk.next;
} while (chunk);

return false;
}

trimStart(charType) {
this.trimStartAborted(charType);
return this;
}
}
19 changes: 19 additions & 0 deletions test/MagicString.js
Expand Up @@ -1173,4 +1173,23 @@ describe( 'MagicString', () => {
assert.equal( s.toString(), ' abcdefghijkl ' );
});
});

describe( 'isEmpty', () => {
it( 'should support isEmpty', () => {
const s = new MagicString( ' abcde fghijkl ' );

assert.equal( s.isEmpty(), false );

s.prepend( ' ' );
s.append( ' ' );
s.remove( 1, 6 );
s.remove( 9, 15 );

assert.equal( s.isEmpty(), false );

s.remove( 15, 16 );

assert.equal( s.isEmpty(), true );
});
});
});