Giter Club home page Giter Club logo

babel-polyfills's Introduction

Babel Polyfills

A set of Babel plugins that enable injecting different polyfills with different strategies in your compiled code. Additionally, this repository contains a package that helps with creating providers for other polyfills.

ℹ️ This repository implements what was initially proposed at babel/babel#10008.

πŸ’‘ If you are looking for some quick setup examples, or just want to see how to migrate your config, please check docs/migration.md.

Usage

The main Babel packages only transform JavaScript syntax: you also need to load a polyfill, to make native functions (Array.prototype.flat) or built-in objects (Reflect) work in older browsers.

The easiest way to do so is to directly load the polyfill using a <script ...> tag:

<script src="https://unpkg.com/[email protected]/minified.js"></script>

However, this simple approach can potentially include a lot of unnecessary code. The Babel plugins implemented in this repository automatically inject the polyfills in your code, while trying to only load what is really needed. It does this based on your compilation targets and on what you are using in your code.

These plugins (we are calling them "polyfill providers") support different injection methods, to better fit your needs.

For example, if you want to inject imports to es-shims polyfills by adding the missing functions to the global objects, you could configure Babel as such:

Configuration Input code Output code
{
  "targets": { "firefox": 65 },
  "plugins": [
    ["polyfill-es-shims", {
      "method": "usage-global"
    }]
  ]
}
Promise.allSettled([
  p1,
  p2
]).finally(() => {
  console.log("Done!");
});
import "promise.prototype.finally/auto";
import "promise.allsettled/auto";

Promise.allSettled([
  p1,
  p2
]).finally(() => {
  console.log("Done!");
});

If you want to see more configuration examples, you can check the migration docs: docs/migration.md.

If you are interested in reading about all the options supported by these plugins, you can check the usage docs: docs/usage.md.

Supported polyfills

Polyfill Plugin Methods
core-js@2 babel-plugin-polyfill-corejs2 entry-global, usage-global and usage-pure
core-js@3 babel-plugin-polyfill-corejs3 entry-global, usage-global and usage-pure
es-shims babel-plugin-polyfill-es-shims usage-global and usage-pure
regenerator-runtime babel-plugin-polyfill-regenerator entry-global, usage-global and usage-pure

πŸ’‘ We are maintaining support for core-js and es-shims, but we encourage you to implement a provider for your own polyfill, or for your favorite one! One of our goals is to encourage competition between different polyfills, to better balance the different trade offs like spec compliancy and code size.

If you want to implement support for a custom polyfill, you can use @babel/helper-define-polyfill-provider. (docs/polyfill-provider.md.)

Injection methods

Polyfill plugins can expose three different injection methods: entry-global, usage-global and usage-pure. Note that polyfill plugins don't automatically add the necessary package(s) to your dependencies, so you must explicitly list them in your package.json.

ℹ️ All the examples assume that you are targeting Chrome 62.

  • The entry-global method replaces a single simple import to the whole polyfill with imports to the specific features not supported by the target environments. It is most useful when you want to be sure that every unsupported function is available, regardless of what you are using in the code you are compiling with Babel. You might want to use this method if:

    1. you are not compiling your dependencies, but you want to be sure that they have all the necessary polyfills;
    2. Babel's detection logic isn't smart enough to understand which functions you are using;
    3. you want to have a single bundled file containing all the polyfills, without needing to regenerate it when your code changes.
    Input code Output code
    import "core-js";
    import "core-js/modules/es7.array.flat-map.js";
    import "core-js/modules/es6.array.sort.js";
    import "core-js/modules/es7.promise.finally.js";
    import "core-js/modules/es7.symbol.async-iterator.js";
    import "core-js/modules/es7.string.trim-left.js";
    import "core-js/modules/es7.string.trim-right.js";
    import "core-js/modules/web.timers.js";
    import "core-js/modules/web.immediate.js";
    import "core-js/modules/web.dom.iterable.js";
  • The usage-global method injects imports to polyfills attached to the global scope, but only for unsupported features which are used in your code. You might want to use this method if:

    1. you need to keep your code size as small as possible, and only include what is effectively used;
    2. your polyfill doesn't support a single entry point, but each of its features must be loaded separately.
    Input code Output code
    foo.flatMap(x => [x, x+1]);
    bar.trimLeft();
    arr.includes(2);
    import "core-js/modules/es.array.flat-map.js";
    import "core-js/modules/es.array.unscopables.flat-map.js";
    import "core-js/modules/es.string.trim-start.js";
    
    foo.flatMap(x => [x, x + 1]);
    bar.trimLeft();
    arr.includes(2);
  • The usage-pure method injects imports to polyfills for unsupported features which are used in your code, without attaching the polyfills to the global scope but importing them as normal functions. You might want to use this method if:

    1. you are a library author, and don't want to "pollute" the global scope with the polyfills you are loading.
    Input code Output code
    foo.flatMap(x => [x, x+1]);
    bar.trimLeft();
    arr.includes(2);
    import _flatMapInstanceProperty from "core-js-pure/stable/instance/flat-map.js";
    import _trimLeftInstanceProperty from "core-js-pure/stable/instance/trim-left.js";
    
    _flatMapInstanceProperty(foo).call(foo, x => [x, x + 1]);
    _trimLeftInstanceProperty(bar).call(bar);
    arr.includes(2);

History and Motivation

In the last three years and a half, @babel/preset-env has shown its full potential in reducing bundle sizes not only by not transpiling supported syntax features, but also by not including unnecessary core-js polyfills.

So far Babel provided three different ways to inject core-js polyfills in the source code:

  • By using @babel/preset-env's useBuiltIns: "entry" option, it is possible to inject self-installing polyfills for every ECMAScript functionality not natively supported by the target browsers;
  • By using @babel/preset-env's useBuiltIns: "usage", Babel will only inject self-installing polyfills for unsupported ECMAScript features but only if they are actually used in the input souce code;
  • By using @babel/plugin-transform-runtime, Babel will inject "pure" polyfills (which, unlike self-installing ones, don't pollute the global scope) for every used ECMAScript feature supported by core-js. This is usually used by library authors.

Our old approach has two main problems:

  • It wasn't possible to use @babel/preset-env's targets option with "pure" polyfills, because @babel/plugin-transform-runtime is a completely separate package.
  • We forced our users to use core-js if they wanted a Babel integration. core-js is a good and comprehensive polyfill, but it doesn't fit the needs of all of our users.

With this new packages we are proposing a solution for both of these problem, while still maintaining full backward compatibility.

Want to contribute?

See our CONTRIBUTING.md to get started with setting up the repo.

babel-polyfills's People

Contributors

agilgur5 avatar andersk avatar charlessuh avatar clarkdo avatar dependabot[bot] avatar dreyks avatar existentialism avatar fangbinwei avatar hzoo avatar jir4 avatar jlhwung avatar jquense avatar liuxingbaoyu avatar ljharb avatar nicolo-ribaudo avatar pustovalov avatar saitonakamura avatar sanyuan0704 avatar thiagoarrais avatar thiry1 avatar vadimka123 avatar vskh avatar wangziling avatar zloirock avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

babel-polyfills's Issues

[preset-env] Add ability to error if polyfills are required

Feature Request

Some corejs polyfills are overly bloated (or have trivial alternatives in many situations) and it can be desirable to avoid the need for them. preset-env already has the ability to detect where polyfills would be required in code via useBuiltIns (and with more accuracy than a linter since it is the tool which actually adds the polyfill!)

Extending the existing concept of the exclude section to provide a way of forbidding individual polyfills would be useful for managing this:

{
  "useBuiltIns": "inline",
  "corejs": 3,
  "polyfills": {
    "web.url": "useBuiltIn", // or true
    "es.string.replace": "exclude",
    "web.immediate": "error"
  }
}

This would replace exclude (with a simple migration path) and has the advantage of having a less ambiguous name.

Unconfigured polyfills could default to either useBuiltIn (to match current behaviour and make it easier to adopt new polyfills) or error (to force developers to consider each newly required polyfill rather than blindly accepting it). I could see arguments for both defaults; not sure what's best (though I personally would prefer an error default).

Do I still need this package to polyfill ?

Hi
I see Rethink polyfilling story was closed because of this project.
But I read here https://babeljs.io/docs/en/babel-polyfill/ "As of Babel 7.4.0, this package has been deprecated"

So my question is I do not need this package to do polyfill with the latest @babel/core (I use version "7.12.13" ), right ?

But since this package was deprecated what is latest document about polyfill using babel ? How much information in Rethink polyfilling story is invalid now ?

Unsure how usage-pure and transform-runtime should work

Sorry for the slew of issues, we are really testing out the work here (it's awesome!). The docs suggest that this can be used instead of corejs specific runtime packages:

{
  "presets": [
    ["@babel/preset-env", {
      "targets": { "firefox": 42 }
    }]
  ],
  "plugins": [
    ["@babel/transform-runtime", {
      "corejs": 3
    }]
  ]
}

It's unclear to me though how this would work for helpers that also need polyfills. like AsyncGenerator. Is this case supposed to be covered?

PRs to port from the main Babel repository

These PRs might already be working in this repo, but we need to check.

  • babel/babel#10372 Don't allow instance properties transformation on namespace #5
  • babel/babel#10146 Inject core-js@3 imports in Program:exit instead of on post() (they are now imported when visiting the node which needs them)
  • babel/babel#10068 feat(transform-runtime): add more type hints for instance methods (probably not the whole PR since it adds many unnecessary hints, but we need to check if I forgot some of them)
  • babel/babel#10284 Replace es.string.reverse with es.array.reverse
  • babel/babel#10207 a variable named 'filter' can be incorrectly transformed by transform-runtime plugin

Issues:

Clarifications regarding migration and backwards compatibility

Hi guys! Thank you for all your great work here, I really think babel-polyfills is the good path to follow. It just took me some time to find it.

Yesterday I started the migration in one library from a @babel/preset-env/@babel/plugin-transform-runtime setup. I carefully read all your notes and some of the source code involved, however, I wrote down some doubts that I would like to clarify before making my changes definitive.

Considering the following situation:

BEFORE AFTER
{
  "presets": [
    ["@babel/preset-env", {
      "spec": true,
      "modules": false,
      "targets": "...",
      "ignoreBrowserslistConfig": true
    }]
  ],
  "plugins": [
    ["@babel/transform-runtime", {
      "version": "^7.17.9",
      "corejs": { "version": 3, "proposals": true },
      "useESModules": true
    }]
  ]
}
{
  "targets": "...",
  "browserslistConfigFile": false,
  "presets": [
    ["@babel/preset-env", {
      "spec": true,
      "modules": false,
      "ignoreBrowserslistConfig": true
    }]
  ],
  "plugins": [
    ["@babel/transform-runtime", {
      "version": "^7.17.9",
    }],
    ["polyfill-corejs3", {
      "method": "usage-pure"
    }]
  ]
}

(Having @babel/runtime as a runtime dependency and @babel/preset-env, @babel/plugin-transform-runtime and babel-plugin-polyfill-corejs3 as development dependencies, after migration.)

The following doubts arise:

  1. Will @babel/runtime helpers be transpiled/polyfilled? Since we are not referencing them from the corejs source anymore (@babel/runtime-corejs3). For example, if @babel/runtime/helpers/asyncToGenerator is used, will Promise be polyfilled inside it? (Without polluting the global scope). (Maybe this could be a problem because I think it is not possible anymore to disable general polyfills in @babel/plugin-transform-runtime while still importing helpers from @babel/runtime-corejs3.)
  2. With babel-plugin-polyfill-corejs3, is it possible to use a specific version of core-js? (like 3.18.1). Should/can we add core-js-pure (or other flavor) as a runtime dependency explicitly in our library?
  3. Can proposals be 'opt-in', like with proposals option in @babel/plugin-transform-runtime?
  4. Will ES6 modules always be used? How does the plugin decide when to use ES6 or CJS?
  5. Is this new system beta? Can it be reliably used in critical projects? With proper testing, etc.

Hope I am not missing or confusing anything. I would really appreciate any insights.

Thank you again!

`Symbol.iterator` should not load full `Symbol` polyfill

// Now:
arr[Symbol.iterator]();
// =>
import "core-js/modules/es.symbol.iterator.js";
import "core-js/modules/es.array.iterator.js";
import "core-js/modules/es.object.to-string.js";
import "core-js/modules/es.string.iterator.js";
import "core-js/modules/web.dom-collections.iterator.js";
import "core-js/modules/es.symbol.js";
import "core-js/modules/es.symbol.description.js";
arr[Symbol.iterator]();

es.symbol and es.symbol.description should not be loaded only on Symbol.iterator - it's too expensive. core-js architecture should allow to use es.symbol.iterator and iterators without those modules.

Promise is polyfilled when using `.toArray`, even if supported by browser

npm install @babel/core @babel/cli babel-plugin-polyfill-corejs3 core-js

Versions:

% npm ls babel-plugin-polyfill-corejs3 @babel/core @babel/cli browserslist caniuse-lite
/Users/dosentmatter/babel
β”œβ”€β”€ @babel/[email protected] 
β”œβ”€β”¬ @babel/[email protected] 
β”‚ └─┬ @babel/[email protected]
β”‚   └─┬ [email protected] 
β”‚     └── [email protected] 
└─┬ [email protected] 
  └─┬ [email protected]
    └── [email protected]  deduped
// .babelrc
{
  "plugins": [
    ["polyfill-corejs3", { "method": "usage-global" }]
  ]
}

I initially noticed issue when using React.Children.toArray, but it seems to happen with use of .toArray with any variable, eg. _.toArray.

Examples:

// all browsers that don't support promises will polyfill Promise
% echo '_.toArray' | BROWSERSLIST='> 0% and not supports promises' npx babel -f stdin.js
"use strict";

require("core-js/modules/es.object.to-string.js");

require("core-js/modules/es.promise.js");

_.toArray;
// All browsers that support promises still polyfills Promise
% echo '_.toArray' | BROWSERSLIST='supports promises' npx babel -f stdin.js
"use strict";

require("core-js/modules/es.object.to-string.js");

require("core-js/modules/es.promise.js");

_.toArray;
// Modern browsers still polyfills Promise
% echo '_.toArray' | BROWSERSLIST='supports es6-module' npx babel -f stdin.js
"use strict";

require("core-js/modules/es.promise.js");

_.toArray;
// Modern browsers using React.Children.toArray still polyfills Promise
% echo 'require("react").Children.toArray' | BROWSERSLIST='supports es6-module' npx babel -f stdin.js
"use strict";

require("core-js/modules/es.promise.js");

require("react").Children.toArray;
// Modern browsers using someVariableName.toArray still polyfills Promise
% echo 'someVariableName.toArray' | BROWSERSLIST='supports es6-module' npx babel -f stdin.js
"use strict";

require("core-js/modules/es.promise.js");

someVariableName.toArray;

Is there a prefered way to use with preset-env useBuiltIns but no polyfills

Sorry for badly titled issue, unsure how to describe this succinctly. We are trying to use babel-polyfills with preset-env but running into an issue where it's not easy to tell preset-env plugins to use builtins without also polyfilling them. In an example

const a = {}
const b = { ...a}

Would include an _extends helper if useBuiltIns is false. Setting it to usage compiles to Object.assign({}, a) which is great but also includes a core-js polyfill. We are currently working around this by doing exclude=[/^(es|es6|es7|esnext|web)\./] which works but feels less than ideal.

core-js absolute path import getting added automatically after compilation

After compiling typescript files to javascript files, automatic import like require("/core-js/modules/es.object.keys.js"); gets added on top of each file.

I am using babel - 7 and have dependency on core-js - 3. react - 17

Because of absolute import paths, this creates an issue when others use this component as a dependency.

babelrc.json is -

{
  "sourceType": "unambiguous",
  "presets": [
    [
      "@babel/preset-env",
      {
        "shippedProposals": true,
        "loose": true
      }
    ],
    "@babel/preset-typescript",
    "@babel/preset-react"
  ],
  "plugins": [
    "@babel/plugin-transform-shorthand-properties",
    "@babel/plugin-transform-block-scoping",
    [
      "@babel/plugin-proposal-decorators",
      {
        "legacy": true
      }
    ],
    [
      "@babel/plugin-proposal-class-properties",
      {
        "loose": true
      }
    ],
    [
      "@babel/plugin-proposal-private-methods",
      {
        "loose": true
      }
    ],
    [
      "@babel/plugin-proposal-private-property-in-object",
      {
        "loose":true
      }
    ],
    "@babel/plugin-proposal-export-default-from",
    "@babel/plugin-syntax-dynamic-import",
    [
      "@babel/plugin-proposal-object-rest-spread",
      {
        "loose": true,
        "useBuiltIns": true
      }
    ],
    "@babel/plugin-transform-classes",
    "@babel/plugin-transform-arrow-functions",
    "@babel/plugin-transform-parameters",
    "@babel/plugin-transform-destructuring",
    "@babel/plugin-transform-spread",
    "@babel/plugin-transform-for-of",
    "babel-plugin-macros",
    "@babel/plugin-proposal-optional-chaining",
    "@babel/plugin-proposal-nullish-coalescing-operator",
    [
      "babel-plugin-polyfill-corejs3",
      {
        "method": "usage-global",
        "absoluteImports": "core-js",
        "version": "3.18.1"
      }
    ]
  ]
}

polyfill-regenerator doesn't support targets

Issue

Hey there, so I've been trying to add this to TSDX in jaredpalmer/tsdx#795 but ran into an issue: jaredpalmer/tsdx#795 (comment). Long story short, polyfill-regenerator doesn't seem to support targets.

If I'm understanding correctly, this line needs to specify targets per the polyfill-provider docs.

Would be happy to write a PR for this and will look into it more tomorrow. I'm not sure if I should just manually input the data from MDN or if I should use babel-compat-data for transform-regenerator? Any guidance would be appreciated

Context

Per above, was looking to get this to work with TSDX, which would add quite a lot of indirect library users of this.

Concretely, I was adding this to replace the now defunct/unmaintained babel-plugin-async-to-promises (that has some correctness bugs) without the downsides of an impure preset-env useBuiltIns or all-or-nothing transform-runtime.

P.S.

Also just wanted to say really happy to see this set of libraries existing to provide a solution for gaps between preset-env useBuiltIns and transform-runtime, solves a long existing problem!

The order of promise and promise.finally after compilation seems to be wrong

Bug Report

  • I would like to work on a fix!

Input Code

Promise.resolve(123).finally(() => console.log('finally'))

Expected behavior

After compiling I got like

image

It can not work at ie11

image

Babel Configuration (babel.config.js, .babelrc, package.json#babel, cli command, .eslintrc)

  • Filename: .babelrc

image

Environment

  • Babel version(s): v7.13.10
  • Node/npm version: Node v12.18.0/npm v6.14.8
  • OS: macOS 10.15.7
  • Monorepo: no
  • How you are using Babel: babel-cli

Here are all the packages i installed

image

Possible Solution

When I reverse the order of the two lines of code, it can run normally

image

Docs: Migration of @babel/transform-runtime

https://github.com/babel/babel-polyfills/blob/main/docs/migration.md has a migration step where it does this:

From

{
  "presets": [
    ["@babel/preset-env", {
      "targets": { "firefox": 42 }
    }]
  ],
  "plugins": [
    ["@babel/transform-runtime", {
      "corejs": 3
    }]
  ]
}

To

{
  "presets": [
    ["@babel/preset-env", {
      "targets": { "firefox": 42 }
    }]
  ],
  "plugins": [
    "@babel/transform-runtime",
    ["polyfill-corejs3", {
      "method": "usage-pure"
    }]
  ]
}

What is the reason that it recommends "method": "usage-pure" and not "method": "usage-global"?

As a user who wants to do the following, using "method": "usage-global" is more correct for me, right?

  • I want to transform my code to my target environment
  • I want to add polyfills automatically in my code (not caring about polluting the global namespace)
  • I want the babel runtime helpers to be re-used via imports (without repetition of babel helpers in each file)

[Bug]: `Object.hasOwn` esnext proposal does not get polyfilled as expected

πŸ’»

  • Would you like to work on a fix?

How are you using Babel?

@babel/cli

Input code

const testObject = { test: 'whatever' }
console.log("Object.hasOwn(test, 'whatever'): ", Object.hasOwn(testObject, 'test'))

const testArray = [1, 2, 5, 9]
console.log('randomArray.lastItem(): ', testArray.lastItem())

Configuration file name

babel.config.json

Configuration

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "targets": {
          "node": "14"
        },
        "useBuiltIns": "usage",
        "corejs": {
          "version": "3.14",
          "proposals": true
        }
      }
    ]
  ]
}

Current and expected behavior

Current:

"use strict";

require("core-js/modules/esnext.array.last-item.js");

const testObject = {
  test: 'whatever'
};
console.log("Object.hasOwn(test, 'whatever'): ", Object.hasOwn(testObject, 'test'));
const testArray = [1, 2, 5, 9];
console.log('randomArray.lastItem(): ', testArray.lastItem());

Expected:

"use strict";

require("core-js/modules/esnext.object.has-own.js");
require("core-js/modules/esnext.array.last-item.js");

const testObject = {
  test: 'whatever'
};
console.log("Object.hasOwn(test, 'whatever'): ", Object.hasOwn(testObject, 'test'));
const testArray = [1, 2, 5, 9];
console.log('randomArray.lastItem(): ', testArray.lastItem());

Environment

  • Babel: v7.14.5
  • corejs: v3.14.0
  • Node: v14.17.0 (LTS)
  • npm: v6.14.13

Possible solution

No response

Additional context

NOTE: The same behavior can be verified with webpack's babel-loader, so this is not specifically related to @babel/cli.

[Bug]: NodeList.prototype.forEach is not polyfilled in pure mode

πŸ’»

  • Would you like to work on a fix?

How are you using Babel?

babel-loader (webpack)

Input code

document.body.childNodes.forEach(x => {
  x;
})

Configuration file name

babel.config.js

Configuration

module.exports = (api) => {
  api.cache.never();

  return {
    sourceType: 'unambiguous',
    plugins: [
      // [
      //   'polyfill-corejs3',
      //   {
      //     method: 'usage-pure'
      //   }
      // ],
      [
        "@babel/plugin-transform-runtime",
        {
          "corejs": 3,
          "version": require('./package.json').dependencies['@babel/runtime-corejs3']
        }
      ]
    ]
  };
};

Current and expected behavior

There are no pollyfills whatsoever in the output. I expect there to be polyfills.

Environment

Node 17 on Windows. See minimal reproduction repo for tool versions.

Possible solution

No response

Additional context

This bug has already been filed in the core-js repo here and I've been told to file here.

Babel is not polyfilling NodeList.prototype.forEach when using @babel/plugin-transform-runtime or polyfill-corejs3 with method set to usage-pure. Babel polyfills correctly with method set to 'usage-global'. Additionally, [1].includes(1) is pollyfilled just fine with the same configs.

Minimal reproduction repo: polyfill-test.zip

Just run npm i && npx webpack.

Better error message when not providing options

Currently if you just run the polyfill without options it will throw with .method must be a string, we should also tell people the options they can choose.

{
  "plugins": ["babel-plugin-polyfill-corejs3"]
}

Something like, this plugin needs options, the method value, etc. And config example

Write docs

I have to write these before making this repo public

Se docs are already in this repository, but I need to expand them for the first release.

(corejs3) `"".replaceAll` not being polyfilled in Node v14 LTS

Please see zloirock/core-js#978 for details on the problem I am seeing (I think there is value in seeing the response given by the maintainer, so that is why I haven't copied the issue contents over here). As mentioned in that issue, please let me know if you cannot reproduce this yourself, and I'll try to provide a minimal case. Let me know if you have any other questions!

[Bug]: Math.clamp is not polyfilled even with "include": ["esnext.math.clamp"]

πŸ’»

  • Would you like to work on a fix?

How are you using Babel?

Programmatic API (babel.transform, babel.parse)

Input code

const source = 'Math.clamp(1, 2, 3)';
const config = {
    presets: [
        [
            '@babel/preset-env',
            {
                'modules': false,
                'corejs': '3.18.0',
                'useBuiltIns': 'usage',
                'shippedProposals': true,
                'include': [
                    'esnext.math.clamp'
                ]
            }
        ]
    ]
};

const { code } = require('@babel/core').transformSync(source, config);

Configuration file name

.babelrc

Configuration

{
    "presets": [
        [
            "@babel/preset-env",
            {
                "modules": false,
                "corejs": "3.18.0",
                "useBuiltIns": "usage",
                "shippedProposals": true,
                "include": [
                    "esnext.math.clamp"
                ]
            }
        ]
    ]
}

Current and expected behavior

Currently it leaves source intact, but I expect it to add core-js/modules/esnext.math.clamp import.

Environment

  System:
    OS: macOS 11.5.2
  Binaries:
    Node: 12.16.3 - /usr/local/bin/node
    Yarn: 1.22.11 - /usr/local/bin/yarn
    npm: 6.14.4 - /usr/local/bin/npm
  npmPackages:
    @babel/core: 7.15.5 => 7.15.5 
    @babel/preset-env: 7.15.6 => 7.15.6 

Possible solution

No response

Additional context

I narrowed it to a minimal reproducible example, but I'm using babel with webpack.

ponyfills

The README.md has two "ponyfills" in them. 🐴-fills πŸ˜†

[@babel/babel-polyfill] allow use of Financial-Times/polyfill-library as polyfills-source

Feature Request

Is your feature request related to a problem? Please describe.
core-js is missing the important things. ChildNode.remove(), fetch(), XMLHttpRequest() ...

Describe the solution you'd like
possibility to use Financial-Times/polyfill-library or any other source of polyfills while keeping the possibility of useBuiltIns: 'usage', so babel-loader still only includes whats necessary.

Describe alternatives you've considered
Including a huge bundle of polyfills and/or gather the ones i need and/or have a mess of a setup of polyfilled and not polyfilled things while having half of the features polyfilled fully automatic by babel/polyfill.

Teachability, Documentation, Adoption, Migration Strategy

{
	test: /\.js$/,
	exclude: /node_modules/,
	use: {
		loader: 'babel-loader',
		options: {
			presets: [
				[
					'@babel/preset-env',
					{
						targets: {
							browsers: [
								'last 2 versions',
								'ie >= 11'
							]
						},
						useBuiltIns: 'usage',
						polyfillSource: 'Financial-Times/polyfill-library' // or somthing like this
					}
				]
			]
		}
	}
}

General timeline for mainstream usage?

I see the repo still notes that these packages are "highly experimental" and "have not been tested in production". Is there a plan for when these will no longer be experimental? No pressure; just trying to get a sense of when this will become the recommended way to deal with polyfills (and/or if there are still some competing ideas within the babel ecosystem in regards to polyfilling).

polyfill-corejs3 inject wrong Number.isNaN polyfill

isNaN: define("number/is-nan", ["es.number.is-safe-integer"]),
isSafeInteger: define("number/is-safe-integer", ["es.number.is-nan"]),

maybe should be

isNaN: define("number/is-nan", ["es.number.is-nan"]), 
 isSafeInteger: define("number/is-safe-integer", ["es.number.is-safe-integer"])

I can provide a reproducible repo if needed

related to vuejs/vue-cli#6324

core.js semver version seems wrong, only considers strict major version

Went to upgrade after #31 was released and noticed that the issue continued to persist. The reason is get-modules-list-for-target-version is being fed 3 for the version by default, which ignores 3.1, 3.2, etc. I tried a few semver-y things to be more inclusive but it seems core-js doesn't support those, so one needs to manually set 3.6 or whatever the latest is, which seems less than ideal.

[Bug]: Array.prototype.at parse wrong with babel/cli

πŸ’»

  • Would you like to work on a fix?

How are you using Babel?

@babel/cli

Input code

case 1(wrong result)

function test() {
    this.array = [];
    var lastIndexOfArray = this.array.at(-1);
}

output:

import "core-js/modules/esnext.string.at.js"; // should be import "core-js/modules/es.array.at.js"

function test() {
  this.array = [];
  var lastIndexOfArray = this.array.at(-1);
}

case 2 (wrong result)

function test() {
    var array = [];
    var lastIndexOfArray = array.at(-1);
}

output(same as input, no core-js added):
function test() {
  var array = [];
  var lastIndexOfArray = array.at(-1);
}

case 3(parse as expected)

function test() {
    var string = '123';
    var lastIndexOfString = string.at(-1);
}

output:
import "core-js/modules/esnext.string.at.js";

function test() {
  var string = '123';
  var lastIndexOfString = string.at(-1);
}

case 4(parse as expected)

function test() {
    this.string = '123';
    var lastIndexOfString = string.at(-1);
}

output:
import "core-js/modules/esnext.string.at.js";

function test() {
  this.string = '123';
  var lastIndexOfString = string.at(-1);
}

Configuration file name

No response

Configuration

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "modules": false,
        "useBuiltIns": "usage",
        "targets": {
          "chrome": 43,
          "ios": 9,
          "edge": 80,
          "firefox": 60
        },
        "corejs": {
          "proposals": true,
          "version": 3
        }
      }
    ],
    "@babel/preset-react"
  ]
}

Current and expected behavior

add corejs es.array.at.js, not esnext.string.at.js

recognize Array.prototype.at

Environment

System:
OS: macOS 11.6.1
Binaries:
Node: 16.13.0 - /usr/local/bin/node
npm: 8.1.0 - /usr/local/bin/npm
npmPackages:
@babel/cli: ^7.16.8 => 7.16.8
@babel/core: ^7.16.7 => 7.16.7
@babel/eslint-parser: ^7.16.5 => 7.16.5
@babel/plugin-proposal-decorators: ^7.16.7 => 7.16.7
@babel/plugin-transform-runtime: ^7.16.8 => 7.16.8
@babel/preset-env: ^7.16.8 => 7.16.8
@babel/preset-react: ^7.16.7 => 7.16.7
@babel/preset-typescript: ^7.16.7 => 7.16.7
@babel/runtime: ^7.16.7 => 7.16.7
babel-jest: ^27.4.6 => 27.4.6
babel-preset-const-enum: ^1.0.0 => 1.0.0
eslint: ^8.6.0 => 8.6.0
jest: ^27.4.7 => 27.4.7

Possible solution

No response

Additional context

No response

Outputting absolute import paths in generated code

Is there an ability to configure the import path of the generated output code to be absolute?

For example, instead of inserting output code like:

import "regenerator-runtime"

the desire is to insert output code like:

import "/my-project/node_modules/some-other-project/node_modules/regenerator-runtime"

For background, see the absoluteRuntime option in @babel/plugin-transform-runtime (see https://babeljs.io/docs/en/babel-plugin-transform-runtime#absoluteruntime)

By default, transform-runtime imports from @babel/runtime/foo directly, but that only works if @babel/runtime is in the node_modules of the file that is being compiled. This can be problematic for nested node_modules, npm-linked modules, or CLIs that reside outside the user's project, among other cases. To avoid worrying about how the runtime module's location is resolved, this allows users to resolve the runtime once up front, and then insert absolute paths to the runtime into the output code.

core-js polyfill: incorrect import paths

Some imports such as eg. Symbol (and others) cannot be resolved, b/c the import paths are incorrect.

With proposals: false:

ERROR in ./src/SNIP
Module not found: Error: Can't resolve 'core-js-pure/stable/symbol.js' in '/home/andornaut/workspace/SNIP...'

This doesn't work because simbol is in core-js-pure/features/. When I change the configuration to proposals: true, then the Symbol ponyfill is looked up in core-js-pure/features/ as expected, but the module path is incorrect:

ERROR in ./src/SNIP
Module not found: Error: Can't resolve 'core-js-pure/features/symbol.js' in '/home/andornaut/workspace/SNIP...'

It attempts to import Symbol at core-js-pure/features/symbol.js, but the module is actually located at core-js-pure/features/symbol/index.js.

On my codebase this issue occurs for the following paths:

core-js-pure/features/map.js
core-js-pure/features/promise.js
core-js-pure/features/set.js
core-js-pure/features/symbol.js

In each case the correct path is the ${sibling directory of the same name without the extension}/index.js and this is true of core-js and core-js-pure, eg. node_modules/core-js/features/symbol/index.js and node_modules/core-js-pure/features/symbol/index.js

Note that I also see this issue with plugin: "polyfill-corejs2" and core-js@2

For instance, this error:

Module not found: Error: Can't resolve 'core-js/library/fn/symbol.js

Where the module is actually in node_modules/core-js/library/fn/symbol/index.js

Environment

.babelrc.js

module.exports =
  {
  presets: [
    "@babel/preset-env"
  ],
  plugins: [
    '@babel/plugin-transform-react-jsx',
    '@babel/transform-runtime',
    ["polyfill-corejs3", {
      method: "usage-pure",
      proposals: true,
    }]
  ]
};

.browserslistrc

> 1%
ie >= 11

babel-polyfill for babel version '6.3.26'

Hi.
I need to add babel-polyfill to my project, in order to fix the issue with 'find' and 'includes' functions in ie11. The project is configured with gulp. I have a gulp task with babel configuration. In the project we use presets es2015. So I need to add babel polyfill but don't know how to add it. Please could you help me?

ownKeys, _objectSpread not imported from @babel/runtime helpers

ownKeys and _objectSpread are inlined for each file using the migration below

Old configuration New configuration
{
  "presets": [
    ["@babel/preset-env", {
      "useBuiltIns": "usage",
      "corejs": 3
    }]
  ],
  "plugins": [
    ["@babel/transform-runtime", {
      "corejs": 3
    }]
  ]
}
{
  "presets": [
    ["@babel/preset-env"]
  ],
  "plugins": [
    "@babel/transform-runtime",
    ["polyfill-corejs3", {
      "method": "usage-pure"
    }]
  ]
}

Note that targets are derived from .browserslistrc

@babel/helper-define-polyfill-provider throws syntax error on node 8

See https://unpkg.com/@babel/[email protected]/lib/normalize-options.js L10

function patternToRegExp(pattern) {
  if (pattern instanceof RegExp) return pattern;

  try {
    return new RegExp(`^${pattern}$`);
  } catch {
    return null;
  }
}

Node 8 does not support optional catch binding and it should have been transpiled according to the root config.

targets: { node: env === "production" ? "6.9" : "current" },

(Did you specify NODE_ENV=production before yarn build? πŸ˜›)

polyfill-corejs3 won't polyfill some Promise static methods with method: "usage-pure"

I've been experimenting with polyfill-corejs3 a bit and tried the following setup (also on this repo https://github.com/giniyat202/babel-polyfill-promise):

.browserslist:

chrome >= 75

.babelrc:

{
  "presets": ["@babel/preset-env"],
  "plugins": [
    [
      "polyfill-corejs3",
      {
        "method": "usage-pure"
      }
    ]
  ]
}

input.js:

Promise.all();
Promise.allSettled();
Promise.any();
Promise.race();

I'm expecting both Promise.allSettled and Promise.any to be polyfilled. However, this is not the case here.

expected output:

"use strict";

var _allSettled = _interopRequireDefault(require("core-js-pure/features/promise/all-settled.js"));

var _any = _interopRequireDefault(require("core-js-pure/features/promise/any.js"));

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

Promise.all();
(0, _allSettled.default)();
(0, _any.default)();
Promise.race();

actual output:

"use strict";

Promise.all();
Promise.allSettled();
Promise.any();
Promise.race();

usage-global correctly provides the two missing polyfills.

I've noticed that these methods are defined without a pure reference:

Promise: {
all: define(null, PromiseDependenciesWithIterators),
allSettled: define(null, [
"es.promise.all-settled",
...PromiseDependenciesWithIterators,
]),
any: define(null, ["es.promise.any", ...PromiseDependenciesWithIterators]),
race: define(null, PromiseDependenciesWithIterators),
try: define(null, [
"esnext.promise.try",
...PromiseDependenciesWithIterators,
]),
},

I've tried passing "promise/all-settled" and "promise/any" there and I started seeing correct output.

Clarification on debug output

Hi,

I'm experimenting with the usage-pure mode to polyfill. The debug output from the plugins seems to indicate that no polyfills are applied - every source file has a debug output of:
Based on your code and targets, the corejs3 polyfill did not add any polyfill.
Based on your code and targets, the regenerator polyfill did not add any polyfill.

However, when I look at the output JS, I can see that polyfills (such as Promise) have been applied (as I would expect). How come none of the applied polyfills are mentioned in the debug output? Am I missing them being applied elsewhere or is this a quirk of the new polyfills plugins? Thanks!

For information:
I have a browserslist config in package.json of > 0.25%, not dead, which gives a targets list of:

Using targets: {
  "chrome": "85",
  "edge": "88",
  "firefox": "85",
  "ie": "11",
  "ios": "12.2",
  "opera": "73",
  "safari": "13.1",
  "samsung": "13"
}

My Babel config looks like this:

{
  "presets": [
    [
      "@babel/typescript",
      {
        "jsxPragma": "h"
      }
    ],
    [
      "@babel/preset-env",
      {
        "useBuiltIns": false,
        //"modules": false,
        "bugfixes": true,
        "debug": true
      }
    ]
  ],
  "plugins": [
    "@babel/proposal-class-properties",
    "@babel/proposal-object-rest-spread",
    [
      "@babel/plugin-transform-react-jsx",
      {
        "pragma": "h",
        "pragmaFrag": "Fragment"
      }
    ],
    [
      "babel-plugin-transform-builtin-extend",
      {
        "globals": ["Error"]
      }
    ],
    [
      "@babel/transform-runtime",
      {
        "regenerator": false,
        "debug": true
      }
    ],
    ["polyfill-corejs3", {
      "method": "usage-pure",
      "debug": true
    }],
    ["polyfill-regenerator", {
      "method": "usage-pure",
      "debug": true
    }]
  ]
}

lodash.debounce for laterLogMissingDependencies delays process exit by 1 second

The lodash.debounce for laterLogMissingDependencies adds a 1 second delay at process exit while it waits for the setTimeout to fire.

const laterLogMissingDependencies = debounce(() => {
logMissing(allMissingDeps);
allMissingDeps = new Set();
}, 1000);

This is a really unfortunate side effect of the default "deferred" for missingDependencies.log. Can we change that default to "per-file"?

Minimal reproducible example

babel.config.js

module.exports = {
  presets: [["@babel/preset-env", { corejs: 3, useBuiltIns: "entry" }]],
};

hello.js

console.log("Hello, world!");

Run

$ yarn add @babel/core @babel/preset-env @babel/register core-js
…
info Direct dependencies
β”œβ”€ @babel/[email protected]
β”œβ”€ @babel/[email protected]
β”œβ”€ @babel/[email protected]
└─ [email protected]
…
$ export BABEL_DISABLE_CACHE=true  # to reproduce more than once
$ time node -r @babel/register hello.js
Hello, world!

real	0m1.366s
user	0m0.383s
sys	0m0.047s

There’s a 1 second delay after printing Hello, world! but before exit.

Unnecessary polyfilling + wrongly renaming imports

I babelify + auto polyfill node_modules too; because it's usually unclear what ES version+browser libraries target nowadays. After switching to babel-polyfills (corejs3), one curious case failed.

For esm5/esm2015 builds of [email protected]; in node_modules/rxjs/_esm5/index.js:

  • babel-polyfills adds import _Observable from "core-js-pure/features/observable/index.js"; at the top of the file.
  • then replaces some (or all) occurences of the term Observable with _Observable.
  • rxjs has a re-export export { Observable } from './internal/Observable';. babel-polyfills replaces that with export { _Observable as Observable } from './internal/Observable';
  • bundler rightfully complains that there's no _Observable in ./internal/Observable.

I see two problems here:

  1. Why polyfill Observable in this case? Observable is imported (or re-exported) from somewhere, it's not the global Observable.
  2. Even if it polyfills, why break the imports?

.method must be one of "entry-global", "usage-global" or "usage-pure" (received "usage-entry")

According to the migration guide:
https://github.com/babel/babel-polyfills/blob/master/docs/migration.md#core-js3

added:

      [
        'polyfill-corejs3',
        {
          method: "usage-entry",
        }
      ],

and got this an error:

Module build failed (from ./node_modules/babel-loader/lib/index.js):
 
Error: [BABEL] /home/circleci/project/app/javascript/packs/lite/lite.js: .method must be one of "entry-global", "usage-global" or "usage-pure" (received "usage-entry") (While processing: "/home/circleci/project/node_modules/babel-plugin-polyfill-corejs3/lib/index.js")
 
    at resolveOptions (/home/circleci/project/node_modules/@babel/helper-define-polyfill-provider/lib/index.js:44:11)
 
    at instantiateProvider (/home/circleci/project/node_modules/@babel/helper-define-polyfill-provider/lib/index.js:77:7)
 
    at /home/circleci/project/node_modules/@babel/helper-define-polyfill-provider/lib/index.js:187:9
 
    at /home/circleci/project/node_modules/@babel/helper-plugin-utils/lib/index.js:19:12
 
    at /home/circleci/project/node_modules/@babel/core/lib/config/full.js:199:14
 

didn't find any mention of usage-entry in the code for babel-plugin-polyfill-corejs3

How do I test / use this library as it is atm?

I am aware that this repo is still experimental but I don't wanna wait.
I already tried my luck using it but I failed.

How do you actually use this repo atm? The packages are not listed on npm yet so how do you wire everything up so that it works?

Ofc I would report back my findings once it is working :)

[Bug]: preset-env with "debug: true" lists every target rather than the one which caused the polyfill

πŸ’»

  • Would you like to work on a fix?

How are you using Babel?

@babel/cli

Input code

// code doesn't really matter, it just needs to cause some polyfills
[...document.querySelectorAll('.something')].forEach(
    (el) => el.classList.remove('something')
);

Configuration file name

babel.config.json

Configuration

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "debug": true,
        "targets": [
          "> 0.25%",
          "not dead",
          "not IE 11"
        ],
        "useBuiltIns": "usage",
        "corejs": "3.6.5"
      }
    ]
  ]
}

Current and expected behavior

Current behavior (started in 7.13.0):

preset-env with "debug: true" lists every target next to every applied polyfill, rather than only the target which caused the polyfill.

Example current behavior:

[babel-polyfill-test/src/test.js]
The corejs3 polyfill added the following polyfills:
  es.object.to-string { "android":"4.4.3", "chrome":"92", "edge":"96", "firefox":"94", "ios":"12.2", "opera":"81", "safari":"13.1", "samsung":"15" }
  web.dom-collections.for-each { "android":"4.4.3", "chrome":"92", "edge":"96", "firefox":"94", "ios":"12.2", "opera":"81", "safari":"13.1", "samsung":"15" }
  es.symbol { "android":"4.4.3", "chrome":"92", "edge":"96", "firefox":"94", "ios":"12.2", "opera":"81", "safari":"13.1", "samsung":"15" }
  es.symbol.description { "android":"4.4.3", "chrome":"92", "edge":"96", "firefox":"94", "ios":"12.2", "opera":"81", "safari":"13.1", "samsung":"15" }
  es.symbol.iterator { "android":"4.4.3", "chrome":"92", "edge":"96", "firefox":"94", "ios":"12.2", "opera":"81", "safari":"13.1", "samsung":"15" }
  es.array.iterator { "android":"4.4.3", "chrome":"92", "edge":"96", "firefox":"94", "ios":"12.2", "opera":"81", "safari":"13.1", "samsung":"15" }
  es.string.iterator { "android":"4.4.3", "chrome":"92", "edge":"96", "firefox":"94", "ios":"12.2", "opera":"81", "safari":"13.1", "samsung":"15" }
  web.dom-collections.iterator { "android":"4.4.3", "chrome":"92", "edge":"96", "firefox":"94", "ios":"12.2", "opera":"81", "safari":"13.1", "samsung":"15" }
  es.array.from { "android":"4.4.3", "chrome":"92", "edge":"96", "firefox":"94", "ios":"12.2", "opera":"81", "safari":"13.1", "samsung":"15" }
  es.array.slice { "android":"4.4.3", "chrome":"92", "edge":"96", "firefox":"94", "ios":"12.2", "opera":"81", "safari":"13.1", "samsung":"15" }
  es.regexp.exec { "android":"4.4.3", "chrome":"92", "edge":"96", "firefox":"94", "ios":"12.2", "opera":"81", "safari":"13.1", "samsung":"15" }
  es.regexp.test { "android":"4.4.3", "chrome":"92", "edge":"96", "firefox":"94", "ios":"12.2", "opera":"81", "safari":"13.1", "samsung":"15" }

Expected behavior (last working version was 7.12.17):

Show the specific targets which caused each polyfill.

Example expected behavior, which is how it worked up to and including 7.12.17:

[babel-polyfill-test/src/test.js] Added following core-js polyfill:
  web.dom-collections.for-each { "android":"4.4.3" }

Environment

@babel/[email protected]
node v16.13.1
npm 8.1.2
Ubuntu 20.04

Possible solution

No response

Additional context

No response

Cannot read properties of undefined (reading 'prototype') (>0.5.2)

⚠️ This seems like a regression between 0.5.1 and 0.5.2.

Hi!

When running webpack with mini-css-extract-plugin we are facing this issue.

TypeError: Cannot read properties of undefined (reading 'prototype')
    at Object.<anonymous> (/dev/repo/node_modules/source-map-loader/dist/cjs.js!/dev/repo/node_modules/core-js/modules/web.dom-exception.stack.js:31:74)
var DOMExceptionPrototype = $DOMException.prototype = NativeDOMException.prototype;

NativeDOMException seems to be undefined, causing the whole thing to trip over.

Node v14 and v16
npm@6
webpack 5

What should I install?

I'm migrating from these:

  1. @babel/plugin-transform-runtime with corejs: false
  2. @babel/preset-env with useBuiltIns: 'usage' and corejs: 3.21

to babel/babel-polyfills. I have already installed: @babel/runtime,@babel/plugin-transform-runtime,core-js@3, and babel-plugin-polyfill-corejs3.

I want to automatically import polyfills for my project and helpers when they're needed. So I installed babel-plugin-polyfill-corejs3 based on the migration guide on this Repo., but my question is: do I need to install this one?

yarn add babel-plugin-polyfill-regenerator --dev

Update:

From my testing I found: With or without ['polyfill-regenerator', { method: 'usage-global' }],, the polyfills for Promise are always added. Does it mean that babel-plugin-polyfill-corejs3 include babel-plugin-polyfill-regenerator?

targets property only accepts object

When I use targets: "> 0.25%, not dead" for the "polyfill-corejs3" plugin, I get an error: Invalid Option: '0' is not a valid target. This also happens when I pass an array (even though I am not sure if this is allowed anyway.

Passing an object works { firefox: 43 }. Why is a string not working?

Also: I noticed, that my compiled file is still full of code which doesnt fit the target e.g. this one:

	// Thank's IE8 for his funny defineProperty
	var descriptors = !fails(function () {
	  return Object.defineProperty({}, 1, { get: function () { return 7; } })[1] != 7;
	});

I thought the goal of babel-polyfills is to get rid of all this?
Atm, the compiled file is actually bigger than what I had before.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.