Skip to content

Commit

Permalink
Merge pull request #1083 from mydea/fn/macro-config-set-non-serializable
Browse files Browse the repository at this point in the history
Throw error when setting non-serializable macro config
  • Loading branch information
ef4 authored Jan 25, 2022
2 parents b9f0f31 + d282f13 commit 5d1f19a
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 0 deletions.
43 changes: 43 additions & 0 deletions packages/macros/src/macros-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,12 @@ export default class MacrosConfig {
);
}

if (!isSerializable(config)) {
throw new Error(
`[Embroider:MacrosConfig] the given config from '${fromPath}' for packageName '${packageName}' is not JSON serializable.`
);
}

let targetPackage = this.resolvePackage(fromPath, packageName);
let peers = getOrCreate(this.configs, targetPackage.root, () => []);
peers.push(config);
Expand Down Expand Up @@ -421,3 +427,40 @@ function defaultMergerFor(pkgRoot: string) {
return Object.assign({}, ...ownConfigs, ...otherConfigs);
};
}

function isSerializable(obj: object): boolean {
if (isScalar(obj)) {
return true;
}

if (Array.isArray(obj)) {
return !obj.some((arrayItem: any) => !isSerializable(arrayItem));
}

if (isPlainObject(obj)) {
for (let property in obj) {
let value = obj[property] as any;
if (!isSerializable(value)) {
return false;
}
}

return true;
}

return false;
}

function isScalar(val: any): boolean {
return (
typeof val === 'undefined' ||
typeof val === 'string' ||
typeof val === 'boolean' ||
typeof val === 'number' ||
val === null
);
}

function isPlainObject(obj: any): obj is Record<string, any> {
return typeof obj === 'object' && obj.constructor === Object && obj.toString() === '[object Object]';
}
42 changes: 42 additions & 0 deletions packages/macros/tests/babel/set-config.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { MacrosConfig } from '../../src/node';
import { allBabelVersions } from './helpers';

describe(`setConfig`, function () {
allBabelVersions(function () {
test('works with empty config', () => {
let config = {};

let macroConfig = MacrosConfig.for({}, __dirname);
macroConfig.setConfig(__filename, 'qunit', config);
});

test('works with POJO config', () => {
let config = {
str: 'yes',
num: 10,
bool: true,
undef: undefined,
nil: null,
arr: ['yes', 10, true, undefined, null, { inArr: true }],
obj: { nested: true },
};

let macroConfig = MacrosConfig.for({}, __dirname);
macroConfig.setConfig(__filename, 'qunit', config);
});

test('throws for non-serializable config', () => {
let config = {
obj: {
regex: /regex/,
},
};

let macroConfig = MacrosConfig.for({}, __dirname);

expect(() => macroConfig.setConfig(__filename, 'qunit', config)).toThrow(
`[Embroider:MacrosConfig] the given config from '${__filename}' for packageName 'qunit' is not JSON serializable.`
);
});
});
});

0 comments on commit 5d1f19a

Please sign in to comment.