Skip to content
This repository has been archived by the owner on Aug 4, 2021. It is now read-only.

add support for edge cases #64

Merged
merged 5 commits into from Jun 4, 2019
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
23 changes: 17 additions & 6 deletions src/dataToEsm.ts
Expand Up @@ -3,6 +3,10 @@ import { DataToEsm } from './pluginutils';

export type Indent = string | null | undefined;

function stringify(obj: any): string {
return (JSON.stringify(obj) || 'undefined').replace(/[\u2028\u2029]/g, char => `\\u${('000' + char.charCodeAt(0).toString(16)).slice(-4)}`);
}

function serializeArray<T>(arr: Array<T>, indent: Indent, baseIndent: string): string {
let output = '[';
const separator = indent ? '\n' + baseIndent + indent : '';
Expand All @@ -19,7 +23,7 @@ function serializeObject<T>(obj: { [key: string]: T }, indent: Indent, baseInden
const keys = Object.keys(obj);
for (let i = 0; i < keys.length; i++) {
const key = keys[i];
const stringKey = makeLegalIdentifier(key) === key ? key : JSON.stringify(key);
const stringKey = makeLegalIdentifier(key) === key ? key : stringify(key);
output += `${i > 0 ? ',' : ''}${separator}${stringKey}:${indent ? ' ' : ''}${serialize(
obj[key],
indent,
Expand All @@ -31,13 +35,15 @@ function serializeObject<T>(obj: { [key: string]: T }, indent: Indent, baseInden

function serialize(obj: any, indent: Indent, baseIndent: string): string {
if (obj === Infinity) return 'Infinity';
if (obj === -Infinity) return '-Infinity';
if (obj === 0 && 1/obj === -Infinity) return '-0';
if (obj instanceof Date) return 'new Date(' + obj.getTime() + ')';
if (obj instanceof RegExp) return obj.toString();
if (typeof obj === 'number' && isNaN(obj)) return 'NaN';
if (obj !== obj) return 'NaN';
if (Array.isArray(obj)) return serializeArray(obj, indent, baseIndent);
if (obj === null) return 'null';
if (typeof obj === 'object') return serializeObject(obj, indent, baseIndent);
return JSON.stringify(obj);
return stringify(obj);
}

const dataToEsm: DataToEsm = function dataToEsm(data, options = {}) {
Expand All @@ -50,9 +56,14 @@ const dataToEsm: DataToEsm = function dataToEsm(data, options = {}) {
options.namedExports === false ||
typeof data !== 'object' ||
Array.isArray(data) ||
data instanceof Date ||
data instanceof RegExp ||
data === null
)
return `export default${_}${serialize(data, options.compact ? null : t, '')};`;
) {
const code = serialize(data, options.compact ? null : t, '');
const __ = _ || (/^[{[\-\/]/.test(code) ? '' : ' ');
return `export default${__}${code};`;
}

let namedExportCode = '';
const defaultExportRows = [];
Expand All @@ -69,7 +80,7 @@ const dataToEsm: DataToEsm = function dataToEsm(data, options = {}) {
)};${n}`;
} else {
defaultExportRows.push(
`${JSON.stringify(key)}: ${serialize(data[key], options.compact ? null : t, '')}`
`${stringify(key)}:${_}${serialize(data[key], options.compact ? null : t, '')}`
);
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/makeLegalIdentifier.ts
Expand Up @@ -15,7 +15,7 @@ export const makeLegalIdentifier: MakeLegalIdentifier = function makeLegalIdenti
str = `_${str}`;
}

return str;
return str || '_';
};

export { makeLegalIdentifier as default };
16 changes: 11 additions & 5 deletions test/dataToEsm.test.ts
Expand Up @@ -15,8 +15,8 @@ describe('dataToEsm', function() {

it('supports non-JSON data', function() {
const date = new Date();
expect(dataToEsm({ inf: Infinity, date, number: NaN, regexp: /.*/ })).toEqual(
'export var inf = Infinity;\nexport var date = new Date(' +
expect(dataToEsm({ inf: -Infinity, date, number: NaN, regexp: /.*/ })).toEqual(
'export var inf = -Infinity;\nexport var date = new Date(' +
date.getTime() +
');\nexport var number = NaN;\nexport var regexp = /.*/;\nexport default {\n\tinf: inf,\n\tdate: date,\n\tnumber: number,\n\tregexp: regexp\n};\n'
);
Expand All @@ -28,11 +28,11 @@ describe('dataToEsm', function() {
).toEqual('export var some="data";export var another="data";export default{some,another};');
expect(
dataToEsm(
{ some: { deep: { object: 'definition', here: 'here' } }, another: 'data' },
{ some: { deep: { object: 'definition', here: 'here' } }, else: { deep: { object: 'definition', here: 'here' } } },
{ compact: true, objectShorthand: false }
)
).toEqual(
'export var some={deep:{object:"definition",here:"here"}};export var another="data";export default{some:some,another:another};'
'export var some={deep:{object:"definition",here:"here"}};export default{some:some,"else":{deep:{object:"definition",here:"here"}}};'
);
});

Expand Down Expand Up @@ -67,7 +67,7 @@ describe('dataToEsm', function() {
});

it('exports default only for null', function() {
expect(dataToEsm(null)).toEqual('export default null;');
expect(dataToEsm(null, { compact: true })).toEqual('export default null;');
});

it('exports default only for primitive values', function() {
Expand All @@ -79,4 +79,10 @@ describe('dataToEsm', function() {
'export var a = "x";\nexport default {\n\ta: a,\n' + '\t"": "y"\n};\n'
);
});

it('avoid U+2029 U+2029 -0 be ignored by JSON.stringify, and avoid it return non-string (undefined) before replacing', function() {
expect(dataToEsm([-0, '\u2028\u2029', undefined, function() {}], { compact: true })).toEqual(
'export default[-0,"\\u2028\\u2029",undefined,undefined];'
);
});
});
4 changes: 4 additions & 0 deletions test/makeLegalIdentifier.test.ts
Expand Up @@ -12,4 +12,8 @@ describe('makeLegalIdentifier', function() {
it('blacklists arguments (https://github.com/rollup/rollup/issues/871)', function() {
expect(makeLegalIdentifier('arguments')).toEqual('_arguments');
});

it('empty', function() {
expect(makeLegalIdentifier('')).toEqual('_');
});
});