Skip to content

Commit 49c2d88

Browse files
committed
add polyfill originals
1 parent 16356cb commit 49c2d88

14 files changed

+130
-0
lines changed

rollup/jsPolyfills/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
### Javascript Polyfills
2+
3+
This is a collection of syntax polyfills either copied directly from or heavily inspired by those used by [Rollup](https://github.com/rollup/rollup) and [Sucrase](https://github.com/alangpierce/sucrase). When either tool uses one of these polyfills during a build, it injects the function source code into each file needing the function, which can lead to a great deal of duplication. For our builds, we have therefore implemented something similar to [`tsc`'s `importHelpers` behavior](https://www.typescriptlang.org/tsconfig#importHelpers): Instead of leaving the polyfills injected in multiple places, we instead replace each injected function with an `import` or `require` statement. This directory is the location from which we import. For simplicity (and greater treeshaking ability when using tools which only work on a file-by-file level), each polyfill lives in its own file.
4+
5+
During build, this directory is copied over to the root level of `@sentry/utils`, and the polyfills are compiled into esm and cjs versions. When the injected implementations are replaced by either `import` or `require` by our rollup plugin, each `import`/`require` pulls from the correct module format's folder. (In other words, the injected `import` statements import from `@sentry/utils/jsPolyfills/esm` and the injected `require` statements pull from `@sentry/utils/jsPolyfills/cjs`.)
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// by checking for loose equality to `null`, we catch both `null` and `undefined`
2+
export async function _asyncNullishCoalesce(lhs, rhsFn) {
3+
return lhs != null ? lhs : rhsFn();
4+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
export async function _asyncOptionalChain(ops) {
2+
let lastAccessLHS = undefined;
3+
let value = ops[0];
4+
let i = 1;
5+
while (i < ops.length) {
6+
const op = ops[i];
7+
const fn = ops[i + 1];
8+
i += 2;
9+
// by checking for loose equality to `null`, we catch both `null` and `undefined`
10+
if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) {
11+
// really we're meaning to return `undefined` as an actual value here, but it saves bytes not to write it
12+
return;
13+
}
14+
if (op === 'access' || op === 'optionalAccess') {
15+
lastAccessLHS = value;
16+
value = await fn(value);
17+
} else if (op === 'call' || op === 'optionalCall') {
18+
value = await fn((...args) => value.call(lastAccessLHS, ...args));
19+
lastAccessLHS = undefined;
20+
}
21+
}
22+
return value;
23+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { _asyncOptionalChain } from './_asyncOptionalChain';
2+
3+
export async function _asyncOptionalChainDelete(ops) {
4+
const result = await _asyncOptionalChain(ops);
5+
// by checking for loose equality to `null`, we catch both `null` and `undefined`
6+
return result == null ? true : result;
7+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export function _createNamedExportFrom(obj, localName, importedName) {
2+
exports[localName] = obj[importedName];
3+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
export function _createStarExport(obj) {
2+
Object.keys(obj)
3+
.filter(key => key !== 'default' && key !== '__esModule')
4+
.forEach(key => {
5+
// eslint-disable-next-line no-prototype-builtins
6+
if (exports.hasOwnProperty(key)) {
7+
return;
8+
}
9+
exports[key] = obj[key];
10+
});
11+
}

rollup/jsPolyfills/_interopDefault.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export function _interopDefault(importTarget) {
2+
return importTarget.__esModule ? importTarget : { default: importTarget };
3+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export function _interopNamespace(importTarget) {
2+
return importTarget.__esModule ? importTarget : { ...importTarget, default: importTarget };
3+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/**
2+
* Rollup and Sucrase have identical polyfills for `import { default as someName } from 'someModule'` and `import
3+
* someName from 'someModule'` syntax, named `_interopDefault` and `_interopRequireDefault`, respectively. For
4+
* simplicity, files with both names have been kept, so that we can replace each injected function with an import of the
5+
* same name.
6+
*
7+
* Sucrase only injects the polyfill when the `imports` transform is used, which we're not currently doing. By contrast,
8+
* Rollup injects its version when building cjs modules, which we do do. Therefore, the actual function definition lives
9+
* in `_interopDefault.js`, so that there's no indirection with the one we know we'll be using. Though we likely we
10+
* likely won't ever this the Sucrase version here, it seemed prudent to keep the stub just in case.
11+
*/
12+
13+
export { _interopDefault as _interopRequireDefault } from './_interopDefault';
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/**
2+
* Rollup and Sucrase both have essentially the same polyfill for `import * as someName from 'someModule'` syntax, named
3+
* `_interopNamespace` and `_interopRequireWildcard`, respectively. For simplicity, files with both names have been kept,
4+
* so that we can replace each injected function with an import of the same name.
5+
*
6+
* Sucrase only injects the polyfill when the `imports` transform is used, which we're not currently doing. By contrast,
7+
* Rollup injects its version when building cjs modules, which we do do. Therefore, the actual function definition lives
8+
* in `_interopNamespace.js`, so that there's no indirection with the one we know we'll be using. Though we likely we
9+
* likely won't ever this the Sucrase version here, it seemed prudent to keep the stub just in case.
10+
*/
11+
12+
export { _interopNamespace as _interopRequireWildcard } from './_interopNamespace';
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// by checking for loose equality to `null`, we catch both `null` and `undefined`
2+
export function _nullishCoalesce(lhs, rhsFn) {
3+
return lhs != null ? lhs : rhsFn();
4+
}

rollup/jsPolyfills/_optionalChain.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
export function _optionalChain(ops) {
2+
let lastAccessLHS = undefined;
3+
let value = ops[0];
4+
let i = 1;
5+
while (i < ops.length) {
6+
const op = ops[i];
7+
const fn = ops[i + 1];
8+
i += 2;
9+
// by checking for loose equality to `null`, we catch both `null` and `undefined`
10+
if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) {
11+
// really we're meaning to return `undefined` as an actual value here, but it saves bytes not to write it
12+
return;
13+
}
14+
if (op === 'access' || op === 'optionalAccess') {
15+
lastAccessLHS = value;
16+
value = fn(value);
17+
} else if (op === 'call' || op === 'optionalCall') {
18+
value = fn((...args) => value.call(lastAccessLHS, ...args));
19+
lastAccessLHS = undefined;
20+
}
21+
}
22+
return value;
23+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { _optionalChain } from './_optionalChain';
2+
3+
export function _optionalChainDelete(ops) {
4+
const result = _optionalChain(ops);
5+
// by checking for loose equality to `null`, we catch both `null` and `undefined`
6+
return result == null ? true : result;
7+
}

rollup/jsPolyfills/index.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
export { _asyncNullishCoalesce } from './_asyncNullishCoalesce.js';
2+
export { _asyncOptionalChain } from './_asyncOptionalChain.js';
3+
export { _asyncOptionalChainDelete } from './_asyncOptionalChainDelete.js';
4+
export { _createNamedExportFrom } from './_createNamedExportFrom.js';
5+
export { _createStarExport } from './_createStarExport.js';
6+
export { _interopDefault } from './_interopDefault.js';
7+
export { _interopNamespace } from './_interopNamespace.js';
8+
export { _interopRequireDefault } from './_interopRequireDefault.js';
9+
export { _interopRequireWildcard } from './_interopRequireWildcard.js';
10+
export { _nullishCoalesce } from './_nullishCoalesce.js';
11+
export { _optionalChain } from './_optionalChain.js';
12+
export { _optionalChainDelete } from './_optionalChainDelete.js';

0 commit comments

Comments
 (0)