Skip to content

Commit 3f1866e

Browse files
authored
Merge pull request #2 from corpusculejs/feat/registry-builtin
Add minimal implementation of customElements registry
2 parents e2eafd6 + 68a2d14 commit 3f1866e

File tree

11 files changed

+156
-137
lines changed

11 files changed

+156
-137
lines changed

README.md

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -51,30 +51,38 @@ import 'https://unpkg.com/@corpuscule/custom-builtin-elements';
5151
To use this polyfill with IE 11 you need the following tools:
5252

5353
- `Symbol` polyfill (with support for `Symbol.hasInstance`).
54-
- `WeakSet` polyfill.
5554
- `Promise` polyfill.
5655
- [@babel/plugin-transform-instanceof](https://www.npmjs.com/package/@babel/plugin-transform-instanceof)
5756
applied to your code that uses `instanceof` against any built-in constructor
5857
(like `HTMLButtonElement` etc.).
5958

6059
Also, for all browsers that do not support native web components, you need an
61-
implementation of the `customElements` registry existing. You may use either the
62-
[`@webcomponents/webcomponentsjs`](https://github.com/webcomponents/polyfills/tree/master/packages/webcomponentsjs)
63-
polyfill to have autonomous custom elements as well or the following stub that
64-
would allow you to use only the customized built-in elements. Note that you have
65-
to place the `customElements` implementation **before** this polyfill.
60+
implementation of the `customElements` registry existing. You have the following
61+
choices:
62+
63+
- Use [`@webcomponents/webcomponentsjs`](https://github.com/webcomponents/polyfills/tree/master/packages/webcomponentsjs),
64+
that will also add support for autonomous custom elements.
65+
- Use the minimal implementation of `customElements` provided by this polyfill
66+
that would allow you to use the customized built-in elements only.
67+
68+
Note that both minimal implementation or `@webcomponents/webcomponentsjs`
69+
polyfill should be executed **before** the main polyfill because it will
70+
override methods of the `customElements` registry.
71+
72+
Examples of adding minimal implementation:
73+
74+
- via npm and ESM:
6675

6776
```javascript
68-
function impl() {
69-
throw new Error('Not supported in this environment');
70-
}
77+
import '@corpuscule/custom-builtin-elements/lib/customElementsBase';
78+
import '@corpuscule/custom-builtin-elements';
79+
```
80+
81+
- via [https://unpkg.com](https://unpkg.com) and `script`:
7182

72-
window.customElements = {
73-
define: impl,
74-
get: impl,
75-
upgrade: impl,
76-
whenDefined: impl,
77-
};
83+
```html
84+
<script src="https://unpkg.com/@corpuscule/custom-builtin-elements/lib/customElementsBase.js">
85+
<script src="https://unpkg.com/@corpuscule/custom-builtin-elements">
7886
```
7987
8088
## Example

__tests__/index.js

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -151,9 +151,7 @@ describe('custom-builtin-elements-polyfill', () => {
151151
}
152152

153153
class Foo {}
154-
expect(() => defineCE(Foo)).toThrowError(
155-
'Not supported in this environment',
156-
);
154+
expect(() => defineCE(Foo)).toThrowError('Not supported');
157155
});
158156
});
159157

@@ -171,9 +169,7 @@ describe('custom-builtin-elements-polyfill', () => {
171169
pending();
172170
}
173171

174-
expect(() => customElements.get('x-foo')).toThrowError(
175-
'Not supported in this environment',
176-
);
172+
expect(() => customElements.get('x-foo')).toThrowError('Not supported');
177173
});
178174
});
179175

@@ -202,9 +198,7 @@ describe('custom-builtin-elements-polyfill', () => {
202198
}
203199

204200
const foo = document.createElement('x-foo');
205-
expect(() => customElements.upgrade(foo)).toThrowError(
206-
'Not supported in this environment',
207-
);
201+
expect(() => customElements.upgrade(foo)).toThrowError('Not supported');
208202
});
209203
});
210204

@@ -222,7 +216,7 @@ describe('custom-builtin-elements-polyfill', () => {
222216
}
223217

224218
expect(() => customElements.whenDefined('x-foo')).toThrowError(
225-
'Not supported in this environment',
219+
'Not supported',
226220
);
227221
});
228222
});

__tests__/polyfills.js

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,5 @@
1-
/* eslint-disable class-methods-use-this */
21
import Promise from 'core-js-pure/es/promise';
32
import Symbol from 'core-js-pure/es/symbol';
4-
import WeakSet from 'core-js-pure/es/weak-set';
5-
6-
if (!('customElements' in window)) {
7-
const fn = () => {
8-
throw new Error('Not supported in this environment');
9-
};
10-
11-
window.customElements = {
12-
define: fn,
13-
get: fn,
14-
upgrade: fn,
15-
whenDefined: fn,
16-
};
17-
}
183

194
if (!('Promise' in window)) {
205
window.Promise = Promise;
@@ -23,7 +8,3 @@ if (!('Promise' in window)) {
238
if (!('Symbol' in window)) {
249
window.Symbol = Symbol;
2510
}
26-
27-
if (!('WeakSet' in window)) {
28-
window.WeakSet = WeakSet;
29-
}

karma.conf.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ module.exports = config => {
3838

3939
files: [
4040
{pattern: '__tests__/polyfills.js', watched: false},
41+
'lib/customElementsBase.js',
4142
'lib/customBuiltInElements.js',
4243
{pattern: '__tests__/index.js', watched: false},
4344
],

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@
55
"main": "lib/customBuiltInElements.js",
66
"module": "lib/customBuiltInElements.js",
77
"files": [
8-
"lib/customBuiltInElements.js"
8+
"lib/customBuiltInElements.js",
9+
"lib/customElementsBase.js"
910
],
1011
"scripts": {
1112
"build": "node scripts/build.js",
1213
"lint": "eslint src/**/*.js",
14+
"size": "npm run build && size-limit",
1315
"test": "npm run build && karma start",
1416
"test:watch": "npm run test -- --watch",
1517
"test:coverage": "npm run test -- --coverage"

rollup.config.js

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,33 @@ const babel = require('rollup-plugin-babel');
22
const cleanup = require('rollup-plugin-cleanup');
33
const nodeResolve = require('rollup-plugin-node-resolve');
44

5-
module.exports = {
6-
input: 'src/index.js',
7-
output: {
8-
file: 'lib/customBuiltInElements.js',
9-
format: 'iife',
10-
name: 'customBuiltInElements',
5+
const plugins = [
6+
nodeResolve(),
7+
babel(),
8+
cleanup({
9+
comments: 'none',
10+
}),
11+
];
12+
13+
module.exports = [
14+
{
15+
input: 'src/index.js',
16+
output: {
17+
file: 'lib/customBuiltInElements.js',
18+
format: 'iife',
19+
name: 'customBuiltInElements',
20+
},
21+
plugins,
22+
treeshake: false,
23+
},
24+
{
25+
input: 'src/customElementsBase.js',
26+
output: {
27+
file: 'lib/customElementsBase.js',
28+
format: 'iife',
29+
name: 'customElementsBase',
30+
},
31+
plugins,
32+
treeshake: false,
1133
},
12-
plugins: [
13-
nodeResolve(),
14-
babel(),
15-
cleanup({
16-
comments: 'none',
17-
}),
18-
],
19-
treeshake: false,
20-
};
34+
];

scripts/build.js

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ const {mkdir, writeFile} = require('fs');
33
const {dirname, resolve} = require('path');
44
const {rollup} = require('rollup');
55
const {promisify} = require('util');
6-
const config = require('../rollup.config');
6+
const configs = require('../rollup.config');
77

88
const mkdirAsync = promisify(mkdir);
99
const writeFileAsync = promisify(writeFile);
@@ -13,19 +13,25 @@ const detection = ' if (detect()) { return; }';
1313

1414
(async () => {
1515
try {
16-
const bundle = await rollup(config);
17-
const generated = await bundle.generate(config.output);
18-
const {
19-
output: [{code}],
20-
} = generated;
16+
await Promise.all(
17+
configs.map(async (config, index) => {
18+
const bundle = await rollup(config);
19+
const generated = await bundle.generate(config.output);
20+
let {
21+
output: [{code}],
22+
} = generated;
2123

22-
const [first, second, ...other] = code.split('\n');
23-
const result = [first, second, detection, ...other].join('\n');
24+
if (index === 0) {
25+
const [first, second, ...other] = code.split('\n');
26+
code = [first, second, detection, ...other].join('\n');
27+
}
2428

25-
const resultFile = resolve(cwd, config.output.file);
29+
const resultFile = resolve(cwd, config.output.file);
2630

27-
await mkdirAsync(dirname(resultFile), {recursive: true});
28-
await writeFileAsync(resultFile, result, 'utf8');
31+
await mkdirAsync(dirname(resultFile), {recursive: true});
32+
await writeFileAsync(resultFile, code, 'utf8');
33+
}),
34+
);
2935
} catch (e) {
3036
console.error(e.stack);
3137
process.exit(1);

src/customElementsBase.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
if (!('customElements' in window)) {
2+
const mock = () => {
3+
throw new Error('Not supported');
4+
};
5+
6+
window.customElements = {
7+
define: mock,
8+
get: mock,
9+
upgrade: mock,
10+
whenDefined: mock,
11+
};
12+
}

src/patchCustomElementRegistry.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ function patchCustomElementRegistry() {
6060

6161
if (!patchedPrototypesRegistry.has(firstChild)) {
6262
setPrototypeOf(firstChild, nativeConstructor.prototype);
63-
patchedPrototypesRegistry.add(firstChild);
63+
patchedPrototypesRegistry.set(firstChild, 0);
6464
}
6565

6666
elementsRegistry[name] = constructor;

src/patchNativeConstructors.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ function attributeChanged(mutations) {
2424
}
2525

2626
function patchNativeConstructors() {
27-
nativeConstructorNames.forEach(nativeConstructorName => {
27+
nativeConstructorNames.forEach(nativeNamePart => {
28+
const nativeConstructorName = `HTML${nativeNamePart}Element`;
2829
const NativeConstructor = window[nativeConstructorName];
2930

3031
class PolyfilledConstructor {

0 commit comments

Comments
 (0)