diff --git a/Cargo.lock b/Cargo.lock index cc93e92c84a..e07d01e2828 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4146,6 +4146,7 @@ dependencies = [ "once_cell", "preset_env_base", "pretty_assertions", + "rustc-hash", "semver 1.0.17", "serde", "serde_json", diff --git a/crates/swc_ecma_preset_env/Cargo.toml b/crates/swc_ecma_preset_env/Cargo.toml index f17d3c4b59e..63be1edc43f 100644 --- a/crates/swc_ecma_preset_env/Cargo.toml +++ b/crates/swc_ecma_preset_env/Cargo.toml @@ -27,6 +27,7 @@ serde_json = "1" st-map = "0.2.0" preset_env_base = { version = "0.4.5", path = "../preset_env_base" } +rustc-hash = "1.1.0" string_enum = { version = "0.4.1", path = "../string_enum" } swc_atoms = { version = "0.5.8", path = "../swc_atoms" } swc_common = { version = "0.31.18", path = "../swc_common" } diff --git a/crates/swc_ecma_preset_env/src/corejs3/builtin.rs b/crates/swc_ecma_preset_env/src/corejs3/builtin.rs new file mode 100644 index 00000000000..dedc38978cd --- /dev/null +++ b/crates/swc_ecma_preset_env/src/corejs3/builtin.rs @@ -0,0 +1,1012 @@ +use once_cell::sync::Lazy; + +use crate::util::{descriptor, CoreJSPolyfillDescriptor, ObjectMap, ObjectMap2}; + +fn dynamic_concat(a: &[&'static str], b: &[&'static str]) -> &'static [&'static str] { + let mut res = Vec::with_capacity(a.len() + b.len()); + + res.extend_from_slice(a); + res.extend_from_slice(b); + + res.leak() +} + +const fn concat2(a: &[&'static str], b: &[&'static str]) -> [&'static str; N] { + assert!(N == a.len() + b.len()); + + let mut res = [""; N]; + let mut idx = 0; + + while idx < a.len() { + res[idx] = a[idx]; + idx += 1; + } + + while idx < a.len() + b.len() { + res[idx] = b[idx - a.len()]; + idx += 1; + } + + res +} + +fn typed(name: &'static str) -> CoreJSPolyfillDescriptor { + let mut global = Vec::with_capacity(1 + TYPED_ARRAY_DEPENDENCIES.len()); + global.push(name); + global.extend_from_slice(TYPED_ARRAY_DEPENDENCIES); + + descriptor(None, global.leak(), Some(name), &[]) +} + +static ARRAY_NATURE_ITERATORS: &[&str] = &["es.array.iterator", "web.dom-collections.iterator"]; + +pub static COMMON_ITERATORS: &[&str] = + &concat2::<3>(ARRAY_NATURE_ITERATORS, &["es.string.iterator"]); + +static ARRAY_NATURE_ITERATORS_WITH_TAG: &[&str] = + &concat2::<3>(ARRAY_NATURE_ITERATORS, &["es.object.to-string"]); + +static COMMON_ITERATORS_WITH_TAG: &[&str] = + &concat2::<4>(COMMON_ITERATORS, &["es.object.to-string"]); + +static ERROR_DEPENDENCIES: &[&str] = &["es.error.cause", "es.error.to-string"]; + +static SUPPRESSED_ERROR_DEPENDENCIES: &[&str] = + &concat2::<3>(&["esnext.suppressed-error.constructor"], ERROR_DEPENDENCIES); + +static TYPED_ARRAY_DEPENDENCIES: &[&str] = &[ + "es.typed-array.at", + "es.typed-array.copy-within", + "es.typed-array.every", + "es.typed-array.fill", + "es.typed-array.filter", + "es.typed-array.find", + "es.typed-array.find-index", + "es.typed-array.find-last", + "es.typed-array.find-last-index", + "es.typed-array.for-each", + "es.typed-array.includes", + "es.typed-array.index-of", + "es.typed-array.iterator", + "es.typed-array.join", + "es.typed-array.last-index-of", + "es.typed-array.map", + "es.typed-array.reduce", + "es.typed-array.reduce-right", + "es.typed-array.reverse", + "es.typed-array.set", + "es.typed-array.slice", + "es.typed-array.some", + "es.typed-array.sort", + "es.typed-array.subarray", + "es.typed-array.to-locale-string", + "es.typed-array.to-reversed", + "es.typed-array.to-sorted", + "es.typed-array.to-string", + "es.typed-array.with", + "es.object.to-string", + "es.array.iterator", + "es.array-buffer.slice", + "esnext.array-buffer.detached", + "esnext.array-buffer.transfer", + "esnext.array-buffer.transfer-to-fixed-length", + "esnext.typed-array.filter-reject", + "esnext.typed-array.group-by", + "esnext.typed-array.to-spliced", + "esnext.typed-array.unique-by", +]; + +pub static PROMISE_DEPENDENCIES: &[&str] = &["es.promise", "es.object.to-string"]; + +static PROMISE_DEPENDENCIES_WITH_ITERATORS: &[&str] = + &concat2::<5>(PROMISE_DEPENDENCIES, COMMON_ITERATORS); + +static SYMBOL_DEPENDENCIES: &[&str] = + &["es.symbol", "es.symbol.description", "es.object.to-string"]; + +static MAP_DEPENDENCIES: &[&str] = &concat2::<19>( + &[ + "es.map", + "esnext.map.delete-all", + "esnext.map.emplace", + "esnext.map.every", + "esnext.map.filter", + "esnext.map.find", + "esnext.map.find-key", + "esnext.map.includes", + "esnext.map.key-of", + "esnext.map.map-keys", + "esnext.map.map-values", + "esnext.map.merge", + "esnext.map.reduce", + "esnext.map.some", + "esnext.map.update", + ], + COMMON_ITERATORS_WITH_TAG, +); + +static SET_DEPENDENCIES: &[&str] = &concat2::<28>( + &[ + "es.set", + "esnext.set.add-all", + "esnext.set.delete-all", + "esnext.set.difference", + "esnext.set.difference.v2", + "esnext.set.every", + "esnext.set.filter", + "esnext.set.find", + "esnext.set.intersection", + "esnext.set.intersection.v2", + "esnext.set.is-disjoint-from", + "esnext.set.is-disjoint-from.v2", + "esnext.set.is-subset-of", + "esnext.set.is-subset-of.v2", + "esnext.set.is-superset-of", + "esnext.set.is-superset-of.v2", + "esnext.set.join", + "esnext.set.map", + "esnext.set.reduce", + "esnext.set.some", + "esnext.set.symmetric-difference", + "esnext.set.symmetric-difference.v2", + "esnext.set.union", + "esnext.set.union.v2", + ], + COMMON_ITERATORS_WITH_TAG, +); + +static WEAK_MAP_DEPENDENCIES: &[&str] = &concat2::<7>( + &[ + "es.weak-map", + "esnext.weak-map.delete-all", + "esnext.weak-map.emplace", + ], + COMMON_ITERATORS_WITH_TAG, +); + +static WEAK_SET_DEPENDENCIES: &[&str] = &concat2::<7>( + &[ + "es.weak-set", + "esnext.weak-set.add-all", + "esnext.weak-set.delete-all", + ], + COMMON_ITERATORS_WITH_TAG, +); + +static DOM_EXCEPTION_DEPENDENCIES: &[&str] = &[ + "web.dom-exception.constructor", + "web.dom-exception.stack", + "web.dom-exception.to-string-tag", + "es.error.to-string", +]; + +static URL_SEARCH_PARAMS_DEPENDENCIES: &[&str] = &concat2::<8>( + &[ + "web.url-search-params", + "web.url-search-params.delete", + "web.url-search-params.has", + "web.url-search-params.size", + ], + COMMON_ITERATORS_WITH_TAG, +); + +static ASYNC_ITERATOR_DEPENDENCIES: &[&str] = + &concat2::<3>(&["esnext.async-iterator.constructor"], PROMISE_DEPENDENCIES); + +static ASYNC_ITERATOR_PROBLEM_METHODS: &[&str] = &[ + "esnext.async-iterator.every", + "esnext.async-iterator.filter", + "esnext.async-iterator.find", + "esnext.async-iterator.flat-map", + "esnext.async-iterator.for-each", + "esnext.async-iterator.map", + "esnext.async-iterator.reduce", + "esnext.async-iterator.some", +]; + +static ITERATOR_DEPENDENCIES: &[&str] = &["esnext.iterator.constructor", "es.object.to-string"]; + +static TYPED_ARRAY_STATIC_METHODS: Lazy> = lazy_map!(Map { + from: define(null, ["es.typed-array.from"]), + fromAsync: define( + null, + [ + "esnext.typed-array.from-async", + PROMISE_DEPENDENCIES_WITH_ITERATORS, + ] + ), + of: define(null, ["es.typed-array.of"]), +}); + +static DATA_VIEW_DEPENDENCIES: &[&str] = &[ + "es.data-view", + "es.array-buffer.slice", + "es.object.to-string", +]; + +pub(crate) static BUILT_INS: Lazy> = lazy_map!(Map{ + AsyncDisposableStack: define("async-disposable-stack", [ + "esnext.async-disposable-stack.constructor", + "es.object.to-string", + "esnext.async-iterator.async-dispose", + "esnext.iterator.dispose", + PROMISE_DEPENDENCIES, + SuppressedERROR_DEPENDENCIES, + ]), + AsyncIterator: define("async-iterator/index", ASYNC_ITERATOR_DEPENDENCIES), + AggregateError: define("aggregate-error", [ + "es.aggregate-error", + ERROR_DEPENDENCIES, + CommonIteratorsWithTag, + "es.aggregate-error.cause", + ]), + ArrayBuffer: define(null, [ + "es.array-buffer.constructor", + "es.array-buffer.slice", + "es.object.to-string", + ]), + DataView: define(null, [ + "es.data-view", + "es.array-buffer.slice", + "es.object.to-string", + ]), + DataView: define(null, DATA_VIEW_DEPENDENCIES), + Date: define(null, ["es.date.to-string"]), + DOMException: define("dom-exception", DOM_EXCEPTION_DEPENDENCIES), + DisposableStack: define("disposable-stack", [ + "esnext.disposable-stack.constructor", + "es.object.to-string", + "esnext.iterator.dispose", + SUPPRESSED_ERROR_DEPENDENCIES, + ]), + Error: define(null, ERROR_DEPENDENCIES), + EvalError: define(null, ERROR_DEPENDENCIES), + Float32Array: typed("es.typed-array.float32-array"), + Float64Array: typed("es.typed-array.float64-array"), + Int8Array: typed("es.typed-array.int8-array"), + Int16Array: typed("es.typed-array.int16-array"), + Int32Array: typed("es.typed-array.int32-array"), + Iterator: define("iterator/index", ITERATOR_DEPENDENCIES), + Uint8Array: typed("es.typed-array.uint8-array"), + Uint8ClampedArray: typed("es.typed-array.uint8-clamped-array"), + Uint16Array: typed("es.typed-array.uint16-array"), + Uint32Array: typed("es.typed-array.uint32-array"), + Map: define("map/index", MAP_DEPENDENCIES), + Number: define(null, ["es.number.constructor"]), + Observable: define("observable/index", [ + "esnext.observable", + "esnext.symbol.observable", + "es.object.to-string", + COMMON_ITERATORS_WITH_TAG, + ]), + Promise: define("promise/index", PROMISE_DEPENDENCIES), + RangeError: define(null, ERROR_DEPENDENCIES), + ReferenceError: define(null, ERROR_DEPENDENCIES), + Reflect: define(null, ["es.reflect.to-string-tag", "es.object.to-string"]), + RegExp: define(null, [ + "es.regexp.constructor", + "es.regexp.dot-all", + "es.regexp.exec", + "es.regexp.sticky", + "es.regexp.to-string", + ]), + Set: define("set/index", SET_DEPENDENCIES), + SuppressedError: define("suppressed-error", SUPPRESSED_ERROR_DEPENDENCIES), + Symbol: define("symbol/index", SYMBOL_DEPENDENCIES), + SyntaxError: define(null, ERROR_DEPENDENCIES), + TypeError: define(null, ERROR_DEPENDENCIES), + URIError: define(null, ERROR_DEPENDENCIES), + URL: define("url/index", ["web.url", URL_SEARCH_PARAMS_DEPENDENCIES]), + URLSearchParams: define( + "url-search-params/index", + URL_SEARCH_PARAMS_DEPENDENCIES + ), + WeakMap: define("weak-map/index", WEAK_MAP_DEPENDENCIES), + WeakSet: define("weak-set/index", WEAK_SET_DEPENDENCIES), + + atob: define("atob", ["web.atob", DOM_EXCEPTION_DEPENDENCIES]), + btoa: define("btoa", ["web.btoa", DOM_EXCEPTION_DEPENDENCIES]), + clearImmediate: define("clear-immediate", ["web.immediate"]), + compositeKey: define("composite-key", ["esnext.composite-key"]), + compositeSymbol: define("composite-symbol", ["esnext.composite-symbol"]), + escape: define("escape", ["es.escape"]), + fetch: define(null, PROMISE_DEPENDENCIES), + globalThis: define("global-this", ["es.global-this"]), + parseFloat: define("parse-float", ["es.parse-float"]), + parseInt: define("parse-int", ["es.parse-int"]), + queueMicrotask: define("queue-microtask", ["web.queue-microtask"]), + self: define("self", ["web.self"]), + setImmediate: define("set-immediate", ["web.immediate"]), + setInterval: define("set-interval", ["web.timers"]), + setTimeout: define("set-timeout", ["web.timers"]), + structuredClone: define("structured-clone", [ + "web.structured-clone", + DOM_EXCEPTION_DEPENDENCIES, + "es.array.iterator", + "es.object.keys", + "es.object.to-string", + "es.map", + "es.set", + ]), + unescape: define("unescape", ["es.unescape"]), +}); + +pub(crate) static STATIC_PROPERTIES: Lazy> = lazy_map!(Map{ + AsyncIterator: Map { + from: define("async-iterator/from", [ + "esnext.async-iterator.from", + ASYNC_ITERATOR_DEPENDENCIES, + AsyncIteratorProblemMethods, + CommonIterators, + ]), + }, + Array: Map { + from: define("array/from", ["es.array.from", "es.string.iterator"]), + fromAsync: define("array/from-async", [ + "esnext.array.from-async", + PROMISE_DEPENDENCIES_WITH_ITERATORS, + ]), + isArray: define("array/is-array", ["es.array.is-array"]), + isTemplateObject: define("array/is-template-object", [ + "esnext.array.is-template-object", + ]), + of: define("array/of", ["es.array.of"]), + }, + + ArrayBuffer: Map { + isView: define(null, ["es.array-buffer.is-view"]), + }, + + BigInt: Map { + range: define("bigint/range", [ + "esnext.bigint.range", + "es.object.to-string", + ]), + }, + + Date: Map { + now: define("date/now", ["es.date.now"]), + }, + + Function: Map { + isCallable: define("function/is-callable", ["esnext.function.is-callable"]), + isConstructor: define("function/is-constructor", [ + "esnext.function.is-constructor", + ]), + }, + + Iterator: Map { + from: define("iterator/from", [ + "esnext.iterator.from", + ITERATOR_DEPENDENCIES, + CommonIterators, + ]), + range: define("iterator/range", [ + "esnext.iterator.range", + "es.object.to-string", + ]), + }, + + JSON: Map { + isRawJSON: define("json/is-raw-json", ["esnext.json.is-raw-json"]), + parse: define("json/parse", ["esnext.json.parse", "es.object.keys"]), + rawJSON: define("json/raw-json", [ + "esnext.json.raw-json", + "es.object.create", + "es.object.freeze", + ]), + stringify: define("json/stringify", ["es.json.stringify"], "es.symbol"), + }, + + Math: Map { + DEG_PER_RAD: define("math/deg-per-rad", ["esnext.math.deg-per-rad"]), + RAD_PER_DEG: define("math/rad-per-deg", ["esnext.math.rad-per-deg"]), + acosh: define("math/acosh", ["es.math.acosh"]), + asinh: define("math/asinh", ["es.math.asinh"]), + atanh: define("math/atanh", ["es.math.atanh"]), + cbrt: define("math/cbrt", ["es.math.cbrt"]), + clamp: define("math/clamp", ["esnext.math.clamp"]), + clz32: define("math/clz32", ["es.math.clz32"]), + cosh: define("math/cosh", ["es.math.cosh"]), + degrees: define("math/degrees", ["esnext.math.degrees"]), + expm1: define("math/expm1", ["es.math.expm1"]), + fround: define("math/fround", ["es.math.fround"]), + f16round: define("math/f16round", ["esnext.math.f16round"]), + fscale: define("math/fscale", ["esnext.math.fscale"]), + hypot: define("math/hypot", ["es.math.hypot"]), + iaddh: define("math/iaddh", ["esnext.math.iaddh"]), + imul: define("math/imul", ["es.math.imul"]), + imulh: define("math/imulh", ["esnext.math.imulh"]), + isubh: define("math/isubh", ["esnext.math.isubh"]), + log10: define("math/log10", ["es.math.log10"]), + log1p: define("math/log1p", ["es.math.log1p"]), + log2: define("math/log2", ["es.math.log2"]), + radians: define("math/radians", ["esnext.math.radians"]), + scale: define("math/scale", ["esnext.math.scale"]), + seededPRNG: define("math/seeded-prng", ["esnext.math.seeded-prng"]), + sign: define("math/sign", ["es.math.sign"]), + signbit: define("math/signbit", ["esnext.math.signbit"]), + sinh: define("math/sinh", ["es.math.sinh"]), + tanh: define("math/tanh", ["es.math.tanh"]), + trunc: define("math/trunc", ["es.math.trunc"]), + umulh: define("math/umulh", ["esnext.math.umulh"]), + }, + + Map: Map { + from: define(null, ["esnext.map.from", MAP_DEPENDENCIES]), + groupBy: define(null, ["esnext.map.group-by", MAP_DEPENDENCIES]), + keyBy: define(null, ["esnext.map.key-by", MAP_DEPENDENCIES]), + of: define(null, ["esnext.map.of", MAP_DEPENDENCIES]), + }, + + Number: Map { + EPSILON: define("number/epsilon", ["es.number.epsilon"]), + MAX_SAFE_INTEGER: define("number/max-safe-integer", [ + "es.number.max-safe-integer", + ]), + MIN_SAFE_INTEGER: define("number/min-safe-integer", [ + "es.number.min-safe-integer", + ]), + fromString: define("number/from-string", ["esnext.number.from-string"]), + isFinite: define("number/is-finite", ["es.number.is-finite"]), + isInteger: define("number/is-integer", ["es.number.is-integer"]), + isNaN: define("number/is-nan", ["es.number.is-nan"]), + isSafeInteger: define("number/is-safe-integer", [ + "es.number.is-safe-integer", + ]), + parseFloat: define("number/parse-float", ["es.number.parse-float"]), + parseInt: define("number/parse-int", ["es.number.parse-int"]), + range: define("number/range", [ + "esnext.number.range", + "es.object.to-string", + ]), + }, + + Object: Map { + assign: define("object/assign", ["es.object.assign"]), + create: define("object/create", ["es.object.create"]), + defineProperties: define("object/define-properties", [ + "es.object.define-properties", + ]), + defineProperty: define("object/define-property", [ + "es.object.define-property", + ]), + entries: define("object/entries", ["es.object.entries"]), + freeze: define("object/freeze", ["es.object.freeze"]), + fromEntries: define("object/from-entries", [ + "es.object.from-entries", + "es.array.iterator", + ]), + getOwnPropertyDescriptor: define("object/get-own-property-descriptor", [ + "es.object.get-own-property-descriptor", + ]), + getOwnPropertyDescriptors: define("object/get-own-property-descriptors", [ + "es.object.get-own-property-descriptors", + ]), + getOwnPropertyNames: define("object/get-own-property-names", [ + "es.object.get-own-property-names", + ]), + getOwnPropertySymbols: define("object/get-own-property-symbols", [ + "es.symbol", + ]), + getPrototypeOf: define("object/get-prototype-of", [ + "es.object.get-prototype-of", + ]), + groupBy: define("object/group-by", [ + "esnext.object.group-by", + "es.object.create", + ]), + hasOwn: define("object/has-own", ["es.object.has-own"]), + is: define("object/is", ["es.object.is"]), + isExtensible: define("object/is-extensible", ["es.object.is-extensible"]), + isFrozen: define("object/is-frozen", ["es.object.is-frozen"]), + isSealed: define("object/is-sealed", ["es.object.is-sealed"]), + keys: define("object/keys", ["es.object.keys"]), + preventExtensions: define("object/prevent-extensions", [ + "es.object.prevent-extensions", + ]), + seal: define("object/seal", ["es.object.seal"]), + setPrototypeOf: define("object/set-prototype-of", [ + "es.object.set-prototype-of", + ]), + values: define("object/values", ["es.object.values"]), + }, + + Promise: Map { + all: define(null, PROMISE_DEPENDENCIES_WITH_ITERATORS), + allSettled: define(null, [ + "es.promise.all-settled", + PROMISE_DEPENDENCIES_WITH_ITERATORS, + ]), + any: define(null, [ + "es.promise.any", + "es.aggregate-error", + PROMISE_DEPENDENCIES_WITH_ITERATORS, + ]), + race: define(null, PROMISE_DEPENDENCIES_WITH_ITERATORS), + try: define(null, ["esnext.promise.try", PROMISE_DEPENDENCIES]), + withResolvers: define(null, [ + "esnext.promise.with-resolvers", + PROMISE_DEPENDENCIES, + ]), + }, + + Reflect: Map { + apply: define("reflect/apply", ["es.reflect.apply"]), + construct: define("reflect/construct", ["es.reflect.construct"]), + defineMetadata: define("reflect/define-metadata", [ + "esnext.reflect.define-metadata", + ]), + defineProperty: define("reflect/define-property", [ + "es.reflect.define-property", + ]), + deleteMetadata: define("reflect/delete-metadata", [ + "esnext.reflect.delete-metadata", + ]), + deleteProperty: define("reflect/delete-property", [ + "es.reflect.delete-property", + ]), + get: define("reflect/get", ["es.reflect.get"]), + getMetadata: define("reflect/get-metadata", [ + "esnext.reflect.get-metadata", + ]), + getMetadataKeys: define("reflect/get-metadata-keys", [ + "esnext.reflect.get-metadata-keys", + ]), + getOwnMetadata: define("reflect/get-own-metadata", [ + "esnext.reflect.get-own-metadata", + ]), + getOwnMetadataKeys: define("reflect/get-own-metadata-keys", [ + "esnext.reflect.get-own-metadata-keys", + ]), + getOwnPropertyDescriptor: define("reflect/get-own-property-descriptor", [ + "es.reflect.get-own-property-descriptor", + ]), + getPrototypeOf: define("reflect/get-prototype-of", [ + "es.reflect.get-prototype-of", + ]), + has: define("reflect/has", ["es.reflect.has"]), + hasMetadata: define("reflect/has-metadata", [ + "esnext.reflect.has-metadata", + ]), + hasOwnMetadata: define("reflect/has-own-metadata", [ + "esnext.reflect.has-own-metadata", + ]), + isExtensible: define("reflect/is-extensible", ["es.reflect.is-extensible"]), + metadata: define("reflect/metadata", ["esnext.reflect.metadata"]), + ownKeys: define("reflect/own-keys", ["es.reflect.own-keys"]), + preventExtensions: define("reflect/prevent-extensions", [ + "es.reflect.prevent-extensions", + ]), + set: define("reflect/set", ["es.reflect.set"]), + setPrototypeOf: define("reflect/set-prototype-of", [ + "es.reflect.set-prototype-of", + ]), + }, + + Set: Map { + from: define(null, ["esnext.set.from", SET_DEPENDENCIES]), + of: define(null, ["esnext.set.of", SET_DEPENDENCIES]), + }, + + String: Map { + cooked: define("string/cooked", ["esnext.string.cooked"]), + dedent: define("string/dedent", [ + "esnext.string.dedent", + "es.string.from-code-point", + "es.weak-map", + ]), + fromCodePoint: define("string/from-code-point", [ + "es.string.from-code-point", + ]), + raw: define("string/raw", ["es.string.raw"]), + }, + + Symbol: Map { + asyncDispose: define("symbol/async-dispose", [ + "esnext.symbol.async-dispose", + "esnext.async-iterator.async-dispose", + ]), + asyncIterator: define("symbol/async-iterator", [ + "es.symbol.async-iterator", + ]), + dispose: define("symbol/dispose", [ + "esnext.symbol.dispose", + "esnext.iterator.dispose", + ]), + for: define("symbol/for", [], "es.symbol"), + hasInstance: define("symbol/has-instance", [ + "es.symbol.has-instance", + "es.function.has-instance", + ]), + isConcatSpreadable: define("symbol/is-concat-spreadable", [ + "es.symbol.is-concat-spreadable", + "es.array.concat", + ]), + isRegistered: define("symbol/is-registered", [ + "esnext.symbol.is-registered", + "es.symbol", + ]), + isRegisteredSymbol: define("symbol/is-registered-symbol", [ + "esnext.symbol.is-registered-symbol", + "es.symbol", + ]), + isWellKnown: define("symbol/is-well-known", [ + "esnext.symbol.is-well-known", + "es.symbol", + ]), + isWellKnownSymbol: define("symbol/is-well-known-symbol", [ + "esnext.symbol.is-well-known-symbol", + "es.symbol", + ]), + iterator: define("symbol/iterator", [ + "es.symbol.iterator", + COMMON_ITERATORS_WITH_TAG, + ]), + keyFor: define("symbol/key-for", [], "es.symbol"), + match: define("symbol/match", ["es.symbol.match", "es.string.match"]), + matcher: define("symbol/matcher", ["esnext.symbol.matcher"]), + matchAll: define("symbol/match-all", [ + "es.symbol.match-all", + "es.string.match-all", + ]), + metadata: define("symbol/metadata", [ + "esnext.symbol.metadata", + "esnext.function.metadata", + ]), + metadataKey: define("symbol/metadata-key", ["esnext.symbol.metadata-key"]), + observable: define("symbol/observable", ["esnext.symbol.observable"]), + patternMatch: define("symbol/pattern-match", [ + "esnext.symbol.pattern-match", + ]), + replace: define("symbol/replace", [ + "es.symbol.replace", + "es.string.replace", + ]), + search: define("symbol/search", ["es.symbol.search", "es.string.search"]), + species: define("symbol/species", [ + "es.symbol.species", + "es.array.species", + ]), + split: define("symbol/split", ["es.symbol.split", "es.string.split"]), + toPrimitive: define("symbol/to-primitive", [ + "es.symbol.to-primitive", + "es.date.to-primitive", + ]), + toStringTag: define("symbol/to-string-tag", [ + "es.symbol.to-string-tag", + "es.object.to-string", + "es.math.to-string-tag", + "es.json.to-string-tag", + ]), + unscopables: define("symbol/unscopables", ["es.symbol.unscopables"]), + }, + + URL: Map { + canParse: define("url/can-parse", ["web.url.can-parse", "web.url"]), + }, + + WeakMap: Map { + from: define(null, ["esnext.weak-map.from", WEAK_MAP_DEPENDENCIES]), + of: define(null, ["esnext.weak-map.of", WEAK_MAP_DEPENDENCIES]), + }, + + WeakSet: Map { + from: define(null, ["esnext.weak-set.from", WEAK_SET_DEPENDENCIES]), + of: define(null, ["esnext.weak-set.of", WEAK_SET_DEPENDENCIES]), + }, + + Int8Array: *TYPED_ARRAY_STATIC_METHODS, + Uint8Array: *TYPED_ARRAY_STATIC_METHODS, + Uint8ClampedArray: *TYPED_ARRAY_STATIC_METHODS, + Int16Array: *TYPED_ARRAY_STATIC_METHODS, + Uint16Array: *TYPED_ARRAY_STATIC_METHODS, + Int32Array: *TYPED_ARRAY_STATIC_METHODS, + Uint32Array: *TYPED_ARRAY_STATIC_METHODS, + Float32Array: *TYPED_ARRAY_STATIC_METHODS, + Float64Array: *TYPED_ARRAY_STATIC_METHODS, + + WebAssembly: Map { + CompileError: define(null, ERROR_DEPENDENCIES), + LinkError: define(null, ERROR_DEPENDENCIES), + RuntimeError: define(null, ERROR_DEPENDENCIES), + }, +}); + +pub(crate) static INSTANCE_PROPERTIES: Lazy> = lazy_map!(Map { + asIndexedPairs: define( + "instance/asIndexedPairs", + [ + "esnext.async-iterator.as-indexed-pairs", + ASYNC_ITERATOR_DEPENDENCIES, + "esnext.iterator.as-indexed-pairs", + ITERATOR_DEPENDENCIES, + ] + ), + at: define( + "instance/at", + [ + // TODO: We should introduce overloaded instance methods definition + // Before that is implemented, the `esnext.string.at` must be the first + // In pure mode, the provider resolves the descriptor as a "pure" `esnext.string.at` + // and treats the compat-data of `esnext.string.at` as the compat-data of + // pure import `instance/at`. The first polyfill here should have the lowest corejs + // supported versions. + "esnext.string.at", + "es.string.at-alternative", + "es.array.at", + ] + ), + anchor: define(null, ["es.string.anchor"]), + big: define(null, ["es.string.big"]), + bind: define("instance/bind", ["es.function.bind"]), + blink: define(null, ["es.string.blink"]), + bold: define(null, ["es.string.bold"]), + codePointAt: define("instance/code-point-at", ["es.string.code-point-at"]), + codePoints: define("instance/code-points", ["esnext.string.code-points"]), + concat: define("instance/concat", ["es.array.concat"], None, ["String"]), + copyWithin: define("instance/copy-within", ["es.array.copy-within"]), + demethodize: define("instance/demethodize", ["esnext.function.demethodize"]), + description: define(null, ["es.symbol", "es.symbol.description"]), + dotAll: define(null, ["es.regexp.dot-all"]), + drop: define( + "instance/drop", + [ + "esnext.async-iterator.drop", + ASYNC_ITERATOR_DEPENDENCIES, + "esnext.iterator.drop", + ITERATOR_DEPENDENCIES, + ] + ), + emplace: define( + "instance/emplace", + ["esnext.map.emplace", "esnext.weak-map.emplace",] + ), + endsWith: define("instance/ends-with", ["es.string.ends-with"]), + entries: define("instance/entries", ARRAY_NATURE_ITERATORS_WITH_TAG), + every: define( + "instance/every", + [ + "es.array.every", + "esnext.async-iterator.every", + // TODO: add async iterator dependencies when we support sub-dependencies + // esnext.async-iterator.every depends on es.promise + // but we don't want to pull es.promise when esnext.async-iterator is disabled + // + // ASYNC_ITERATOR_DEPENDENCIES + "esnext.iterator.every", + ITERATOR_DEPENDENCIES, + ] + ), + exec: define(null, ["es.regexp.exec"]), + fill: define("instance/fill", ["es.array.fill"]), + filter: define( + "instance/filter", + [ + "es.array.filter", + "esnext.async-iterator.filter", + "esnext.iterator.filter", + ITERATOR_DEPENDENCIES, + ] + ), + filterReject: define("instance/filterReject", ["esnext.array.filter-reject"]), + finally: define(null, ["es.promise.finally", PROMISE_DEPENDENCIES]), + find: define( + "instance/find", + [ + "es.array.find", + "esnext.async-iterator.find", + "esnext.iterator.find", + ITERATOR_DEPENDENCIES, + ] + ), + findIndex: define("instance/find-index", ["es.array.find-index"]), + findLast: define("instance/find-last", ["es.array.find-last"]), + findLastIndex: define("instance/find-last-index", ["es.array.find-last-index",]), + fixed: define(null, ["es.string.fixed"]), + flags: define("instance/flags", ["es.regexp.flags"]), + flatMap: define( + "instance/flat-map", + [ + "es.array.flat-map", + "es.array.unscopables.flat-map", + "esnext.async-iterator.flat-map", + "esnext.iterator.flat-map", + ITERATOR_DEPENDENCIES, + ] + ), + flat: define( + "instance/flat", + ["es.array.flat", "es.array.unscopables.flat"] + ), + getFloat16: define( + null, + ["esnext.data-view.get-float16", DATA_VIEW_DEPENDENCIES] + ), + getUint8Clamped: define( + null, + ["esnext.data-view.get-uint8-clamped", DATA_VIEW_DEPENDENCIES] + ), + getYear: define(null, ["es.date.get-year"]), + group: define("instance/group", ["esnext.array.group"]), + groupBy: define("instance/group-by", ["esnext.array.group-by"]), + groupByToMap: define( + "instance/group-by-to-map", + [ + "esnext.array.group-by-to-map", + "es.map", + "es.object.to-string", + ] + ), + groupToMap: define( + "instance/group-to-map", + ["esnext.array.group-to-map", "es.map", "es.object.to-string",] + ), + fontcolor: define(null, ["es.string.fontcolor"]), + fontsize: define(null, ["es.string.fontsize"]), + forEach: define( + "instance/for-each", + [ + "es.array.for-each", + "esnext.async-iterator.for-each", + "esnext.iterator.for-each", + ITERATOR_DEPENDENCIES, + "web.dom-collections.for-each", + ] + ), + includes: define( + "instance/includes", + ["es.array.includes", "es.string.includes",] + ), + indexed: define( + "instance/indexed", + [ + "esnext.async-iterator.indexed", + ASYNC_ITERATOR_DEPENDENCIES, + "esnext.iterator.indexed", + ITERATOR_DEPENDENCIES, + ] + ), + indexOf: define("instance/index-of", ["es.array.index-of"]), + isWellFormed: define("instance/is-well-formed", ["es.string.is-well-formed"]), + italic: define(null, ["es.string.italics"]), + join: define(null, ["es.array.join"]), + keys: define("instance/keys", ARRAY_NATURE_ITERATORS_WITH_TAG), + lastIndex: define(null, ["esnext.array.last-index"]), + lastIndexOf: define("instance/last-index-of", ["es.array.last-index-of"]), + lastItem: define(null, ["esnext.array.last-item"]), + link: define(null, ["es.string.link"]), + map: define( + "instance/map", + [ + "es.array.map", + "esnext.async-iterator.map", + "esnext.iterator.map", + ] + ), + match: define(null, ["es.string.match", "es.regexp.exec"]), + matchAll: define( + "instance/match-all", + ["es.string.match-all", "es.regexp.exec",] + ), + name: define(null, ["es.function.name"]), + padEnd: define("instance/pad-end", ["es.string.pad-end"]), + padStart: define("instance/pad-start", ["es.string.pad-start"]), + push: define("instance/push", ["es.array.push"]), + reduce: define( + "instance/reduce", + [ + "es.array.reduce", + "esnext.async-iterator.reduce", + "esnext.iterator.reduce", + ITERATOR_DEPENDENCIES, + ] + ), + reduceRight: define("instance/reduce-right", ["es.array.reduce-right"]), + repeat: define("instance/repeat", ["es.string.repeat"]), + replace: define(null, ["es.string.replace", "es.regexp.exec"]), + replaceAll: define( + "instance/replace-all", + [ + "es.string.replace-all", + "es.string.replace", + "es.regexp.exec", + ] + ), + reverse: define("instance/reverse", ["es.array.reverse"]), + search: define(null, ["es.string.search", "es.regexp.exec"]), + setFloat16: define( + null, + ["esnext.data-view.set-float16", DATA_VIEW_DEPENDENCIES] + ), + setUint8Clamped: define( + null, + ["esnext.data-view.set-uint8-clamped", DATA_VIEW_DEPENDENCIES] + ), + setYear: define(null, ["es.date.set-year"]), + slice: define("instance/slice", ["es.array.slice"]), + small: define(null, ["es.string.small"]), + some: define( + "instance/some", + [ + "es.array.some", + "esnext.async-iterator.some", + "esnext.iterator.some", + ITERATOR_DEPENDENCIES, + ] + ), + sort: define("instance/sort", ["es.array.sort"]), + splice: define("instance/splice", ["es.array.splice"]), + split: define(null, ["es.string.split", "es.regexp.exec"]), + startsWith: define("instance/starts-with", ["es.string.starts-with"]), + sticky: define(null, ["es.regexp.sticky"]), + strike: define(null, ["es.string.strike"]), + sub: define(null, ["es.string.sub"]), + substr: define(null, ["es.string.substr"]), + sup: define(null, ["es.string.sup"]), + take: define( + "instance/take", + [ + "esnext.async-iterator.take", + ASYNC_ITERATOR_DEPENDENCIES, + "esnext.iterator.take", + ITERATOR_DEPENDENCIES, + ] + ), + test: define(null, ["es.regexp.test", "es.regexp.exec"]), + toArray: define( + "instance/to-array", + [ + "esnext.async-iterator.to-array", + ASYNC_ITERATOR_DEPENDENCIES, + "esnext.iterator.to-array", + ITERATOR_DEPENDENCIES, + ] + ), + toAsync: define( + null, + [ + "esnext.iterator.to-async", + ITERATOR_DEPENDENCIES, + ASYNC_ITERATOR_DEPENDENCIES, + AsyncIteratorProblemMethods, + ] + ), + toExponential: define(null, ["es.number.to-exponential"]), + toFixed: define(null, ["es.number.to-fixed"]), + toGMTString: define(null, ["es.date.to-gmt-string"]), + toISOString: define(null, ["es.date.to-iso-string"]), + toJSON: define(null, ["es.date.to-json", "web.url.to-json"]), + toPrecision: define(null, ["es.number.to-precision"]), + toReversed: define("instance/to-reversed", ["es.array.to-reversed"]), + toSorted: define( + "instance/to-sorted", + ["es.array.to-sorted", "es.array.sort",] + ), + toSpliced: define("instance/to-spliced", ["es.array.to-spliced"]), + toString: define( + null, + [ + "es.object.to-string", + "es.error.to-string", + "es.date.to-string", + "es.regexp.to-string", + ] + ), + toWellFormed: define("instance/to-well-formed", ["es.string.to-well-formed"]), + trim: define("instance/trim", ["es.string.trim"]), + trimEnd: define("instance/trim-end", ["es.string.trim-end"]), + trimLeft: define("instance/trim-left", ["es.string.trim-start"]), + trimRight: define("instance/trim-right", ["es.string.trim-end"]), + trimStart: define("instance/trim-start", ["es.string.trim-start"]), + uniqueBy: define("instance/unique-by", ["esnext.array.unique-by", "es.map"]), + unshift: define("instance/unshift", ["es.array.unshift"]), + unThis: define("instance/un-this", ["esnext.function.un-this"]), + values: define("instance/values", ARRAY_NATURE_ITERATORS_WITH_TAG), + with: define("instance/with", ["es.array.with"]), + __defineGetter__: define(null, ["es.object.define-getter"]), + __defineSetter__: define(null, ["es.object.define-setter"]), + __lookupGetter__: define(null, ["es.object.lookup-getter"]), + __lookupSetter__: define(null, ["es.object.lookup-setter"]), + __proto__: define(null, ["es.object.proto"]), +}); diff --git a/crates/swc_ecma_preset_env/src/corejs3/data.rs b/crates/swc_ecma_preset_env/src/corejs3/data.rs index 9ae2cf2a090..b9bd982d3df 100644 --- a/crates/swc_ecma_preset_env/src/corejs3/data.rs +++ b/crates/swc_ecma_preset_env/src/corejs3/data.rs @@ -2,820 +2,6 @@ use once_cell::sync::Lazy; use preset_env_base::version::Version; use swc_common::collections::AHashMap; -use crate::util::{DataMap, FeatureMap}; - -const fn concat2(a: &[&'static str], b: &[&'static str]) -> [&'static str; N] { - assert!(N == a.len() + b.len()); - - let mut res = [""; N]; - let mut idx = 0; - - while idx < a.len() { - res[idx] = a[idx]; - idx += 1; - } - - while idx < a.len() + b.len() { - res[idx] = b[idx - a.len()]; - idx += 1; - } - - res -} - -static ARRAY_NATURE_ITERATORS: &[&str] = &["es.array.iterator", "web.dom-collections.iterator"]; - -pub static COMMON_ITERATORS: &[&str] = - &concat2::<3>(&["es.string.iterator"], ARRAY_NATURE_ITERATORS); - -static ARRAY_NATURE_ITERATORS_WITH_TAG: &[&str] = - &concat2::<3>(&["es.object.to-string"], ARRAY_NATURE_ITERATORS); - -static COMMON_ITERATORS_WITH_TAG: &[&str] = - &concat2::<4>(&["es.object.to-string"], COMMON_ITERATORS); - -static ITERATOR: &[&str] = &["esnext.iterator.constructor", "es.object.to-string"]; - -pub static PROMISE_DEPENDENCIES: &[&str] = &["es.promise", "es.object.to-string"]; - -static PROMISE_DEPENDENCIES_WITH_ITERATORS: &[&str] = - &concat2::<5>(PROMISE_DEPENDENCIES, COMMON_ITERATORS); - -static TYPED_ARRAY_STATIC_METHODS: FeatureMap = data_map!(Map { - from: &["es.typed-array.from"], - fromAsync: TYPED_FROM_ASYNC, - of: &["es.typed-array.of"], -}); - -static ASYNC_ITERATOR: &[&str] = - &concat2::<3>(&["esnext.async-iterator.constructor"], PROMISE_DEPENDENCIES); - -static TYPED_FROM_ASYNC: &[&str] = &concat2::<6>( - &["esnext.typed-array.from-async"], - PROMISE_DEPENDENCIES_WITH_ITERATORS, -); - -static SYMBOL_DEPENDENCIES: &[&str] = - &["es.symbol", "es.symbol.description", "es.object.to-string"]; - -static MAP_DEPENDENCIES: &[&str] = &concat2::<19>( - &[ - "es.map", - "esnext.map.delete-all", - "esnext.map.emplace", - "esnext.map.every", - "esnext.map.filter", - "esnext.map.find", - "esnext.map.find-key", - "esnext.map.includes", - "esnext.map.key-of", - "esnext.map.map-keys", - "esnext.map.map-values", - "esnext.map.merge", - "esnext.map.reduce", - "esnext.map.some", - "esnext.map.update", - ], - COMMON_ITERATORS_WITH_TAG, -); - -static SET_DEPENDENCIES: &[&str] = &concat2::<28>( - &[ - "es.set", - "esnext.set.add-all", - "esnext.set.delete-all", - "esnext.set.difference", - "esnext.set.difference.v2", - "esnext.set.every", - "esnext.set.filter", - "esnext.set.find", - "esnext.set.intersection", - "esnext.set.intersection.v2", - "esnext.set.is-disjoint-from", - "esnext.set.is-disjoint-from.v2", - "esnext.set.is-subset-of", - "esnext.set.is-subset-of.v2", - "esnext.set.is-superset-of", - "esnext.set.is-superset-of.v2", - "esnext.set.join", - "esnext.set.map", - "esnext.set.reduce", - "esnext.set.some", - "esnext.set.symmetric-difference", - "esnext.set.symmetric-difference.v2", - "esnext.set.union", - "esnext.set.union.v2", - ], - COMMON_ITERATORS_WITH_TAG, -); - -static WEAK_MAP_DEPENDENCIES: &[&str] = &concat2::<7>( - &[ - "es.weak-map", - "esnext.weak-map.delete-all", - "esnext.weak-map.emplace", - ], - COMMON_ITERATORS_WITH_TAG, -); - -static WEAK_SET_DEPENDENCIES: &[&str] = &concat2::<7>( - &[ - "es.weak-set", - "esnext.weak-set.add-all", - "esnext.weak-set.delete-all", - ], - COMMON_ITERATORS_WITH_TAG, -); - -static URL_SEARCH_PARAMS_DEPENDENCIES: &[&str] = &concat2::<6>( - &["web.url-search-params", "web.url-search-params.size"], - COMMON_ITERATORS_WITH_TAG, -); - -pub static REGEXP_DEPENDENCIES: &[&str] = &[ - "es.regexp.constructor", - "es.regexp.dot-all", - "es.regexp.exec", - "es.regexp.sticky", - "es.regexp.to-string", -]; - -static TYPED_ARRAY: &[&str] = &[ - "es.typed-array.at", - "es.typed-array.copy-within", - "es.typed-array.every", - "es.typed-array.fill", - "es.typed-array.filter", - "es.typed-array.find", - "es.typed-array.find-index", - "es.typed-array.find-last", - "es.typed-array.find-last-index", - "es.typed-array.for-each", - "es.typed-array.includes", - "es.typed-array.index-of", - "es.typed-array.iterator", - "es.typed-array.join", - "es.typed-array.last-index-of", - "es.typed-array.map", - "es.typed-array.reduce", - "es.typed-array.reduce-right", - "es.typed-array.reverse", - "es.typed-array.set", - "es.typed-array.slice", - "es.typed-array.some", - "es.typed-array.sort", - "es.typed-array.subarray", - "es.typed-array.to-locale-string", - "es.typed-array.to-reversed", - "es.typed-array.to-sorted", - "es.typed-array.to-string", - "es.typed-array.with", - "es.object.to-string", - "es.array.iterator", - "es.array-buffer.slice", - "esnext.array-buffer.detached", - "esnext.array-buffer.transfer", - "esnext.array-buffer.transfer-to-fixed-length", - "esnext.typed-array.filter-reject", - "esnext.typed-array.group-by", - "esnext.typed-array.to-spliced", - "esnext.typed-array.unique-by", -]; - -static FLOAT32_ARRAY: &[&str] = &concat2::<40>(TYPED_ARRAY, &["es.typed-array.float32-array"]); -static FLOAT64_ARRAY: &[&str] = &concat2::<40>(TYPED_ARRAY, &["es.typed-array.float64-array"]); -static INT8_ARRAY: &[&str] = &concat2::<40>(TYPED_ARRAY, &["es.typed-array.int8-array"]); -static INT16_ARRAY: &[&str] = &concat2::<40>(TYPED_ARRAY, &["es.typed-array.int16-array"]); -static INT32_ARRAY: &[&str] = &concat2::<40>(TYPED_ARRAY, &["es.typed-array.int32-array"]); -static UINT8_ARRAY: &[&str] = &concat2::<40>(TYPED_ARRAY, &["es.typed-array.uint8-array"]); -static UINT8_CLAMPED_ARRAY: &[&str] = - &concat2::<40>(TYPED_ARRAY, &["es.typed-array.uint8-clamped-array"]); -static UINT16_ARRAY: &[&str] = &concat2::<40>(TYPED_ARRAY, &["es.typed-array.uint16-array"]); -static UINT32_ARRAY: &[&str] = &concat2::<40>(TYPED_ARRAY, &["es.typed-array.uint32-array"]); - -static OBSERVEABLE: &[&str] = &concat2::<7>( - &[ - "esnext.observable", - "esnext.symbol.observable", - "es.object.to-string", - ], - COMMON_ITERATORS_WITH_TAG, -); - -static URL_DEP: &[&str] = &concat2::<7>(&["web.url"], URL_SEARCH_PARAMS_DEPENDENCIES); - -static DOM_EXCEPTION: &[&str] = &[ - "web.dom-exception.constructor", - "web.dom-exception.stack", - "web.dom-exception.to-string-tag", - "es.error.to-string", -]; -static ATOB: &[&str] = &concat2::<5>(DOM_EXCEPTION, &["web.atob"]); -static BTOA: &[&str] = &concat2::<5>(DOM_EXCEPTION, &["web.btoa"]); -static STRUCTURE_CLONE: &[&str] = &concat2::<10>( - DOM_EXCEPTION, - &[ - "web.structured-clone", - "es.array.iterator", - "es.object.keys", - "es.object.to-string", - "es.map", - "es.set", - ], -); - -static ERROR_DEP: &[&str] = &["es.error.cause", "es.error.to-string"]; -static SUPPRESSED_ERROR_DEP: &[&str] = - &concat2::<3>(ERROR_DEP, &["esnext.suppressed-error.constructor"]); - -static AGGREGATE_ERROR_DEP: &[&str] = &concat2::<8>( - COMMON_ITERATORS_WITH_TAG, - &[ - "es.aggregate-error", - "es.error.cause", - "es.error.to-string", - "es.aggregate-error.cause", - ], -); - -static DISPOSABLE_STACK_DEP: &[&str] = &concat2::<6>( - SUPPRESSED_ERROR_DEP, - &[ - "esnext.disposable-stack.constructor", - "es.object.to-string", - "esnext.iterator.dispose", - ], -); - -static ASYNC_DISPOSABLE_STACK_DEP: &[&str] = &concat2::<9>( - &concat2::<5>(SUPPRESSED_ERROR_DEP, PROMISE_DEPENDENCIES), - &[ - "esnext.async-disposable-stack.constructor", - "es.object.to-string", - "esnext.async-iterator.async-dispose", - "esnext.iterator.dispose", - ], -); - -pub static BUILTINS: DataMap<&[&str]> = data_map!(Map { - AsyncDisposableStack: ASYNC_DISPOSABLE_STACK_DEP, - AsyncIterator: ASYNC_ITERATOR, - AggregateError: AGGREGATE_ERROR_DEP, - ArrayBuffer: [ - "es.array-buffer.constructor", - "es.array-buffer.slice", - "es.object.to-string", - ], - DataView: [ - "es.data-view", - "es.array-buffer.slice", - "es.object.to-string" - ], - Date: ["es.date.to-string"], - DOMException: DOM_EXCEPTION, - DisposableStack: DISPOSABLE_STACK_DEP, - Error: ERROR_DEP, - EvalError: ERROR_DEP, - Iterator: ITERATOR, - Float32Array: FLOAT32_ARRAY, - Float64Array: FLOAT64_ARRAY, - Int8Array: INT8_ARRAY, - Int16Array: INT16_ARRAY, - Int32Array: INT32_ARRAY, - Uint8Array: UINT8_ARRAY, - Uint8ClampedArray: UINT8_CLAMPED_ARRAY, - Uint16Array: UINT16_ARRAY, - Uint32Array: UINT32_ARRAY, - Map: MAP_DEPENDENCIES, - Number: ["es.number.constructor"], - Observable: OBSERVEABLE, - Promise: PROMISE_DEPENDENCIES, - RangeError: ERROR_DEP, - ReferenceError: ERROR_DEP, - Reflect: ["es.reflect.to-string-tag", "es.object.to-string"], - RegExp: REGEXP_DEPENDENCIES, - Set: SET_DEPENDENCIES, - SuppressedError: SUPPRESSED_ERROR_DEP, - Symbol: SYMBOL_DEPENDENCIES, - SyntaxError: ERROR_DEP, - TypeError: ERROR_DEP, - URIError: ERROR_DEP, - URL: URL_DEP, - URLSearchParams: URL_SEARCH_PARAMS_DEPENDENCIES, - WeakMap: WEAK_MAP_DEPENDENCIES, - WeakSet: WEAK_SET_DEPENDENCIES, - - atob: ATOB, - btoa: BTOA, - clearImmediate: ["web.immediate"], - compositeKey: ["esnext.composite-key"], - compositeSymbol: ["esnext.composite-symbol"], - escape: ["es.escape"], - fetch: PROMISE_DEPENDENCIES, - globalThis: ["es.global-this"], - parseFloat: ["es.parse-float"], - parseInt: ["es.parse-int"], - queueMicrotask: ["web.queue-microtask"], - self: ["web.self"], - setTimeout: ["web.timers"], - setInterval: ["web.timers"], - setImmediate: ["web.immediate"], - structuredClone: STRUCTURE_CLONE, - unescape: ["es.unescape"], -}); - -static ASYNC_ITERATOR_WITH_ITERATOR: &[&str] = &concat2::<5>(ITERATOR, ASYNC_ITERATOR); - -static INDEXED_PAIRS: &[&str] = &concat2::<7>( - &[ - "esnext.async-iterator.as-indexed-pairs", - "esnext.iterator.as-indexed-pairs", - ], - ASYNC_ITERATOR_WITH_ITERATOR, -); - -static DROP: &[&str] = &concat2::<7>( - &["esnext.async-iterator.drop", "esnext.iterator.drop"], - ASYNC_ITERATOR_WITH_ITERATOR, -); - -static EVERY: &[&str] = &concat2::<5>( - &[ - "es.array.every", - "esnext.async-iterator.every", - "esnext.iterator.every", - ], - ITERATOR, -); - -static FILTER: &[&str] = &concat2::<5>( - &[ - "es.array.filter", - "esnext.async-iterator.filter", - "esnext.iterator.filter", - ], - ITERATOR, -); - -static FIND: &[&str] = &concat2::<5>( - &[ - "es.array.find", - "esnext.async-iterator.find", - "esnext.iterator.find", - ], - ITERATOR, -); - -static FLAT_MAP: &[&str] = &concat2::<6>( - &[ - "es.array.flat-map", - "es.array.unscopables.flat-map", - "esnext.async-iterator.flat-map", - "esnext.iterator.flat-map", - ], - ITERATOR, -); - -static FOR_EACH: &[&str] = &concat2::<6>( - &[ - "es.array.for-each", - "esnext.async-iterator.for-each", - "esnext.iterator.for-each", - "web.dom-collections.for-each", - ], - ITERATOR, -); - -static REDUCE: &[&str] = &concat2::<5>( - &[ - "es.array.reduce", - "esnext.async-iterator.reduce", - "esnext.iterator.reduce", - ], - ITERATOR, -); - -static SOME: &[&str] = &concat2::<5>( - &[ - "es.array.some", - "esnext.async-iterator.some", - "esnext.iterator.some", - ], - ITERATOR, -); - -static TAKE: &[&str] = &concat2::<7>( - &["esnext.async-iterator.take", "esnext.iterator.take"], - ASYNC_ITERATOR_WITH_ITERATOR, -); - -static TO_ARRAY: &[&str] = &concat2::<7>( - &["esnext.async-iterator.to-array", "esnext.iterator.to-array"], - ASYNC_ITERATOR_WITH_ITERATOR, -); - -static ASYNC_ITERATOR_METHOD: &[&str] = &[ - "esnext.async-iterator.every", - "esnext.async-iterator.filter", - "esnext.async-iterator.find", - "esnext.async-iterator.flat-map", - "esnext.async-iterator.for-each", - "esnext.async-iterator.map", - "esnext.async-iterator.reduce", - "esnext.async-iterator.some", -]; - -static TO_ASYNC: &[&str] = &concat2::<14>( - &["esnext.iterator.to-async"], - &concat2::<13>(ASYNC_ITERATOR_WITH_ITERATOR, ASYNC_ITERATOR_METHOD), -); - -static PROMISE_FINALLY: &[&str] = &concat2::<3>(&["es.promise.finally"], PROMISE_DEPENDENCIES); - -pub static INSTANCE_PROPERTIES: DataMap<&[&str]> = data_map!(Map { - asIndexedPairs: INDEXED_PAIRS, - // TODO: check type of variable - at: ["esnext.string.at", "es.string.at-alternative", "es.array.at"], - anchor: ["es.string.anchor"], - big: ["es.string.big"], - bind: ["es.function.bind"], - blink: ["es.string.blink"], - bold: ["es.string.bold"], - codePointAt: ["es.string.code-point-at"], - codePoints: ["esnext.string.code-points"], - concat: ["es.array.concat"], - copyWithin: ["es.array.copy-within"], - description: ["es.symbol", "es.symbol.description"], - dotAll: [ "es.regexp.dot-all"], - drop: DROP, - emplace: ["esnext.map.emplace", "esnext.weak-map.emplace"], - endsWith: ["es.string.ends-with"], - entries: ARRAY_NATURE_ITERATORS_WITH_TAG, - every: EVERY, - exec: ["es.regexp.exec"], - fill: ["es.array.fill"], - filter: FILTER, - filterReject: "esnext.array.filter-reject", - finally: PROMISE_FINALLY, - find: FIND, - findIndex: ["es.array.find-index"], - findLast: ["es.array.find-last"], - findLastIndex: ["es.array.find-last-index"], - fixed: ["es.string.fixed"], - flags: ["es.regexp.flags"], - flat: ["es.array.flat", "es.array.unscopables.flat"], - flatMap: FLAT_MAP, - fontcolor: ["es.string.fontcolor"], - fontsize: ["es.string.fontsize"], - forEach: FOR_EACH, - getYear: "es.date.get-year", - group: ["esnext.array.group"], - groupBy: "esnext.array.group-by", - groupByToMap: ["esnext.array.group-by-to-map", "es.map", "es.object.to-string"], - groupToMap:["esnext.array.group-to-map", "es.map", "es.object.to-string"], - includes: ["es.array.includes", "es.string.includes"], - indexOf: ["es.array.index-of"], - isWellFormed: ["esnext.string.is-well-formed"], - italics: ["es.string.italics"], - join: ["es.array.join"], - keys: ARRAY_NATURE_ITERATORS_WITH_TAG, - lastIndex: ["esnext.array.last-index"], - lastIndexOf: ["es.array.last-index-of"], - lastItem: ["esnext.array.last-item"], - link: ["es.string.link"], - map: ["es.array.map", "esnext.async-iterator.map", "esnext.iterator.map"], - match: ["es.string.match", "es.regexp.exec"], - matchAll: ["es.string.match-all", "es.regexp.exec"], - name: ["es.function.name"], - padEnd: ["es.string.pad-end"], - padStart: ["es.string.pad-start"], - push: ["es.array.push"], - reduce: REDUCE, - reduceRight: ["es.array.reduce-right"], - repeat: ["es.string.repeat"], - replace: ["es.string.replace", "es.regexp.exec"], - replaceAll: ["es.string.replace-all", "es.string.replace","es.regexp.exec"], - reverse: ["es.array.reverse"], - search: ["es.string.search", "es.regexp.exec"], - setYear: ["es.date.set-year"], - slice: ["es.array.slice"], - small: ["es.string.small"], - some: SOME, - sort: ["es.array.sort"], - splice: ["es.array.splice"], - split: ["es.string.split", "es.regexp.exec"], - startsWith: ["es.string.starts-with"], - sticky:["es.regexp.sticky"], - strike: ["es.string.strike"], - sub: ["es.string.sub"], - substr: ["es.string.substr"], - sup: ["es.string.sup"], - take: TAKE, - test: ["es.regexp.test", "es.regexp.exec"], - toArray: TO_ARRAY, - toAsync: TO_ASYNC, - toExponential: "es.number.to-exponential", - toFixed: ["es.number.to-fixed"], - toGMTString: "es.date.to-gmt-string", - toISOString: ["es.date.to-iso-string"], - toJSON: ["es.date.to-json", "web.url.to-json"], - toPrecision: ["es.number.to-precision"], - toReversed: ["es.array.to-reversed"], - toSorted: ["es.array.to-sorted", "es.array.sort"], - toSpliced: "es.array.to-spliced", - toString: ["es.object.to-string", "es.error.to-string", "es.date.to-string", "es.regexp.to-string"], - toWellFormed: ["esnext.string.to-well-formed"], - trim: ["es.string.trim"], - trimEnd: ["es.string.trim-end"], - trimLeft: ["es.string.trim-start"], - trimRight: ["es.string.trim-end"], - trimStart: ["es.string.trim-start"], - uniqueBy: ["esnext.array.unique-by", "es.map"], - unshift: ["es.array.unshift"], - unThis: "esnext.function.un-this", - values: ARRAY_NATURE_ITERATORS_WITH_TAG, - with: "es.array.with", - __defineGetter__: ["es.object.define-getter"], - __defineSetter__: ["es.object.define-setter"], - __lookupGetter__: ["es.object.lookup-getter"], - __lookupSetter__: ["es.object.lookup-setter"], - __proto__: ["es.object.proto"], -}); - -static ASYNC_ITER_FROM: &[&str] = &concat2::<15>( - &["esnext.async-iterator.from"], - &concat2::<14>( - ASYNC_ITERATOR, - &concat2::<11>(ASYNC_ITERATOR_METHOD, COMMON_ITERATORS), - ), -); -static FROM_ASYNC: &[&str] = &concat2::<6>( - &["esnext.array.from-async"], - PROMISE_DEPENDENCIES_WITH_ITERATORS, -); -static ALL_SETTLED: &[&str] = &concat2::<6>( - &["es.promise.all-settled"], - PROMISE_DEPENDENCIES_WITH_ITERATORS, -); -static PROMISE_ANY: &[&str] = &concat2::<7>( - &["es.promise.any", "es.aggregate-error"], - PROMISE_DEPENDENCIES_WITH_ITERATORS, -); -static PROMISE_TRY: &[&str] = - &concat2::<6>(&["esnext.promise.try"], PROMISE_DEPENDENCIES_WITH_ITERATORS); - -static MAP_FROM: &[&str] = &concat2::<20>(&["esnext.map.from"], MAP_DEPENDENCIES); -static MAP_GROUP_BY: &[&str] = &concat2::<20>(&["esnext.map.group-by"], MAP_DEPENDENCIES); -static MAP_KEY_BY: &[&str] = &concat2::<20>(&["esnext.map.key-by"], MAP_DEPENDENCIES); -static MAP_OF: &[&str] = &concat2::<20>(&["esnext.map.key-of"], MAP_DEPENDENCIES); - -static SET_FROM: &[&str] = &concat2::<29>(&["esnext.set.from"], SET_DEPENDENCIES); -static SET_OF: &[&str] = &concat2::<29>(&["esnext.set.of"], SET_DEPENDENCIES); - -static WEAK_MAP_FROM: &[&str] = &concat2::<8>(&["esnext.weak-map.from"], WEAK_MAP_DEPENDENCIES); -static WEAK_MAP_OF: &[&str] = &concat2::<8>(&["esnext.weak-map.of"], WEAK_MAP_DEPENDENCIES); - -static WEAK_SET_FROM: &[&str] = &concat2::<8>(&["esnext.weak-set.from"], WEAK_SET_DEPENDENCIES); -static WEAK_SET_OF: &[&str] = &concat2::<8>(&["esnext.weak-set.of"], WEAK_SET_DEPENDENCIES); - -static SYMBOL_ITERATOR: &[&str] = &concat2::<5>(&["es.symbol.iterator"], COMMON_ITERATORS_WITH_TAG); - -pub static STATIC_PROPERTIES: DataMap> = data_map!(Map { - AsyncIterator: Map { - from: ASYNC_ITER_FROM, - }, - Array: Map { - from: ["es.array.from", "es.string.iterator"], - fromAsync: FROM_ASYNC, - isArray: ["es.array.is-array"], - isTemplateObject: "esnext.array.is-template-object", - of: ["es.array.of"], - }, - - ArrayBuffer: Map { - isView: ["es.array-buffer.is-view"], - }, - - BigInt: Map { - range: ["esnext.bigint.range", "es.object.to-string"], - }, - - Date: Map { now: "es.date.now" }, - - Function: Map { - isCallable: "esnext.function.is-callable", - isConstructor: "esnext.function.is-constructor", - }, - - Iterator: Map { - from: ["esnext.iterator.from"], - range: [ - "esnext.iterator.range", - "es.object.to-string", - ], - }, - - JSON: Map { - isRawJSON: ["esnext.json.is-raw-json"], - parse: ["esnext.json.parse", "es.object.keys"], - rawJSON: [ - "esnext.json.raw-json", - "es.object.create", - "es.object.freeze", - ], - stringify: ["es.json.stringify"], - }, - - Object: Map { - assign: "es.object.assign", - create: "es.object.create", - defineProperty: "es.object.define-property", - defineProperties: "es.object.define-properties", - entries: "es.object.entries", - freeze: "es.object.freeze", - fromEntries: ["es.object.from-entries", "es.array.iterator"], - getOwnPropertyDescriptor: "es.object.get-own-property-descriptor", - getOwnPropertyDescriptors: "es.object.get-own-property-descriptors", - getOwnPropertyNames: "es.object.get-own-property-names", - getOwnPropertySymbols: "es.symbol", - getPrototypeOf: "es.object.get-prototype-of", - hasOwn: "es.object.has-own", - is: "es.object.is", - isExtensible: "es.object.is-extensible", - isFrozen: "es.object.is-frozen", - isSealed: "es.object.is-sealed", - keys: "es.object.keys", - preventExtensions: "es.object.prevent-extensions", - seal: "es.object.seal", - setPrototypeOf: "es.object.set-prototype-of", - values: "es.object.values", - }, - - Math: Map { - DEG_PER_RAD: "esnext.math.deg-per-rad", - RAD_PER_DEG: "esnext.math.rad-per-deg", - acosh: "es.math.acosh", - asinh: "es.math.asinh", - atanh: "es.math.atanh", - cbrt: "es.math.cbrt", - clamp: "esnext.math.clamp", - clz32: "es.math.clz32", - cosh: "es.math.cosh", - degrees: "esnext.math.degrees", - expm1: "es.math.expm1", - fround: "es.math.fround", - fscale: "esnext.math.fscale", - hypot: "es.math.hypot", - iaddh: "esnext.math.iaddh", - imul: "es.math.imul", - imulh: "esnext.math.imulh", - isubh: "esnext.math.isubh", - log1p: "es.math.log1p", - log10: "es.math.log10", - log2: "es.math.log2", - radians: "esnext.math.radians", - scale: "esnext.math.scale", - seededPRNG: "esnext.math.seeded-prng", - sign: "es.math.sign", - signbit: "esnext.math.signbit", - sinh: "es.math.sinh", - tanh: "es.math.tanh", - trunc: "es.math.trunc", - umulh: "esnext.math.umulh", - }, - - String: Map { - cooked: "esnext.string.cooked", - dedent: [ - "esnext.string.dedent", - "es.string.from-code-point", - "es.weak-map", - ], - fromCodePoint: "es.string.from-code-point", - raw: "es.string.raw", - }, - - Number: Map { - EPSILON: "es.number.epsilon", - MIN_SAFE_INTEGER: "es.number.min-safe-integer", - MAX_SAFE_INTEGER: "es.number.max-safe-integer", - fromString: "esnext.number.from-string", - isFinite: "es.number.is-finite", - isInteger: "es.number.is-integer", - isSafeInteger: "es.number.is-safe-integer", - isNaN: "es.number.is-nan", - parseFloat: "es.number.parse-float", - parseInt: "es.number.parse-int", - range: [ - "esnext.number.range", - "es.object.to-string", - ], - }, - - Map: Map { - from: MAP_FROM, - groupBy: MAP_GROUP_BY, - keyBy: MAP_KEY_BY, - of: MAP_OF, - }, - - Set: Map { - from: SET_FROM, - of: SET_OF, - }, - - WeakMap: Map { - from: WEAK_MAP_FROM, - of: WEAK_MAP_OF, - }, - - WeakSet: Map { - from: WEAK_SET_FROM, - of: WEAK_SET_OF, - }, - - Promise: Map { - all: PROMISE_DEPENDENCIES_WITH_ITERATORS, - allSettled: ALL_SETTLED, - any: PROMISE_ANY, - race: PROMISE_DEPENDENCIES_WITH_ITERATORS, - try: PROMISE_TRY, - }, - - Reflect: Map { - apply: "es.reflect.apply", - construct: "es.reflect.construct", - defineMetadata: "esnext.reflect.define-metadata", - defineProperty: "es.reflect.define-property", - deleteMetadata: "esnext.reflect.delete-metadata", - deleteProperty: "es.reflect.delete-property", - get: "es.reflect.get", - getMetadata: "esnext.reflect.get-metadata", - getMetadataKeys: "esnext.reflect.get-metadata-keys", - getOwnMetadata: "esnext.reflect.get-own-metadata", - getOwnMetadataKeys: "esnext.reflect.get-own-metadata-keys", - getOwnPropertyDescriptor: "es.reflect.get-own-property-descriptor", - getPrototypeOf: "es.reflect.get-prototype-of", - has: "es.reflect.has", - hasMetadata: "esnext.reflect.has-metadata", - hasOwnMetadata: "esnext.reflect.has-own-metadata", - isExtensible: "es.reflect.is-extensible", - metadata: "esnext.reflect.metadata", - ownKeys: "es.reflect.own-keys", - preventExtensions: "es.reflect.prevent-extensions", - set: "es.reflect.set", - setPrototypeOf: "es.reflect.set-prototype-of", - }, - - Symbol: Map { - asyncDispose: ["esnext.symbol.async-dispose"], - asyncIterator: ["es.symbol.async-iterator"], - dispose: ["esnext.symbol.dispose"], - for: ["es.symbol"], - hasInstance: ["es.symbol.has-instance", "es.function.has-instance"], - isConcatSpreadable: ["es.symbol.is-concat-spreadable", "es.array.concat"], - isRegistered: ["esnext.symbol.is-registered", "es.symbol"], - isWellKnown: ["esnext.symbol.is-well-known", "es.symbol"], - iterator: SYMBOL_ITERATOR, - keyFor: ["es.symbol"], - match: ["es.symbol.match", "es.string.match"], - matcher: ["es.symbol.matcher"], - matchAll: ["es.symbol.match-all", "es.string.match-all"], - metadata: "esnext.symbol.metadata", - metadataKey: ["esnext.symbol.metadata-key"], - observable: ["esnext.symbol.observable"], - patternMatch: ["esnext.symbol.pattern-match"], - replace: ["es.symbol.replace", "es.string.replace"], - search: ["es.symbol.search", "es.string.search"], - species: ["es.symbol.species", "es.array.species"], - split: ["es.symbol.split", "es.string.split"], - toPrimitive: ["es.symbol.to-primitive", "es.date.to-primitive"], - toStringTag: [ - "es.symbol.to-string-tag", - "es.object.to-string", - "es.math.to-string-tag", - "es.json.to-string-tag", - ], - unscopables: ["es.symbol.unscopables"], - }, - - Int8Array: &TYPED_ARRAY_STATIC_METHODS, - Uint8Array: &TYPED_ARRAY_STATIC_METHODS, - Uint8ClampedArray: &TYPED_ARRAY_STATIC_METHODS, - Int16Array: &TYPED_ARRAY_STATIC_METHODS, - Uint16Array: &TYPED_ARRAY_STATIC_METHODS, - Int32Array: &TYPED_ARRAY_STATIC_METHODS, - Uint32Array: &TYPED_ARRAY_STATIC_METHODS, - Float32Array: &TYPED_ARRAY_STATIC_METHODS, - Float64Array: &TYPED_ARRAY_STATIC_METHODS, - - WebAssembly: Map { - CompileError: ERROR_DEP, - LinkError: ERROR_DEP, - RuntimeError: ERROR_DEP, - }, -}); - pub static POSSIBLE_GLOBAL_OBJECTS: &[&str] = &["global", "globalThis", "self", "window"]; pub static MODULES_BY_VERSION: Lazy> = Lazy::new(|| { diff --git a/crates/swc_ecma_preset_env/src/corejs3/mod.rs b/crates/swc_ecma_preset_env/src/corejs3/mod.rs index f062303c5eb..d7319c6f888 100644 --- a/crates/swc_ecma_preset_env/src/corejs3/mod.rs +++ b/crates/swc_ecma_preset_env/src/corejs3/mod.rs @@ -1,5 +1,6 @@ pub(crate) use self::{entry::Entry, usage::UsageVisitor}; +mod builtin; mod compat; mod data; mod entry; diff --git a/crates/swc_ecma_preset_env/src/corejs3/usage.rs b/crates/swc_ecma_preset_env/src/corejs3/usage.rs index 2d0359d4c01..097766d056c 100644 --- a/crates/swc_ecma_preset_env/src/corejs3/usage.rs +++ b/crates/swc_ecma_preset_env/src/corejs3/usage.rs @@ -5,17 +5,14 @@ use swc_common::DUMMY_SP; use swc_ecma_ast::*; use swc_ecma_visit::{noop_visit_type, Visit, VisitWith}; -use super::data::{BUILTINS, MODULES_BY_VERSION}; -use crate::{ - corejs3::{ - compat::DATA as CORE_JS_COMPAT_DATA, - data::{ - COMMON_ITERATORS, INSTANCE_PROPERTIES, POSSIBLE_GLOBAL_OBJECTS, PROMISE_DEPENDENCIES, - REGEXP_DEPENDENCIES, STATIC_PROPERTIES, - }, +use super::{ + builtin::{ + BUILT_INS, COMMON_ITERATORS, INSTANCE_PROPERTIES, PROMISE_DEPENDENCIES, STATIC_PROPERTIES, }, - util::DataMapExt, - Versions, + data::{MODULES_BY_VERSION, POSSIBLE_GLOBAL_OBJECTS}, +}; +use crate::{ + corejs3::compat::DATA as CORE_JS_COMPAT_DATA, util::CoreJSPolyfillDescriptor, Versions, }; pub(crate) struct UsageVisitor { @@ -56,8 +53,16 @@ impl UsageVisitor { } } + fn add(&mut self, desc: &CoreJSPolyfillDescriptor) { + let deps = desc.global; + + // TODO: Exclude based on object + + self.may_inject_global(deps) + } + /// Add imports - fn add(&mut self, features: &[&'static str]) { + fn may_inject_global(&mut self, features: &[&'static str]) { let UsageVisitor { shipped_proposals, is_any_target, @@ -90,7 +95,7 @@ impl UsageVisitor { } fn add_builtin(&mut self, built_in: &str) { - if let Some(features) = BUILTINS.get_data(built_in) { + if let Some(features) = BUILT_INS.get(built_in) { self.add(features) } } @@ -113,15 +118,15 @@ impl UsageVisitor { self.add_builtin(prop); } - if let Some(map) = STATIC_PROPERTIES.get_data(obj) { - if let Some(features) = map.get_data(prop) { + if let Some(map) = STATIC_PROPERTIES.get(&**obj) { + if let Some(features) = map.get(&**prop) { self.add(features); return; } } } - if let Some(features) = INSTANCE_PROPERTIES.get_data(prop) { + if let Some(features) = INSTANCE_PROPERTIES.get(&**prop) { self.add(features); } } @@ -155,7 +160,7 @@ impl Visit for UsageVisitor { fn visit_array_pat(&mut self, p: &ArrayPat) { p.visit_children_with(self); - self.add(COMMON_ITERATORS) + self.may_inject_global(COMMON_ITERATORS) } fn visit_assign_expr(&mut self, e: &AssignExpr) { @@ -185,16 +190,9 @@ impl Visit for UsageVisitor { fn visit_call_expr(&mut self, e: &CallExpr) { e.visit_children_with(self); - match &e.callee { - Callee::Import(_) => self.add(PROMISE_DEPENDENCIES), - Callee::Expr(expr) => match **expr { - Expr::Ident(ref ident) if ident.sym == js_word!("RegExp") => { - self.add(REGEXP_DEPENDENCIES) - } - _ => {} - }, - _ => {} - }; + if let Callee::Import(_) = &e.callee { + self.may_inject_global(PROMISE_DEPENDENCIES) + } } fn visit_expr(&mut self, e: &Expr) { @@ -209,7 +207,7 @@ impl Visit for UsageVisitor { fn visit_expr_or_spread(&mut self, e: &ExprOrSpread) { e.visit_children_with(self); if e.spread.is_some() { - self.add(COMMON_ITERATORS) + self.may_inject_global(COMMON_ITERATORS) } } @@ -217,14 +215,14 @@ impl Visit for UsageVisitor { fn visit_for_of_stmt(&mut self, s: &ForOfStmt) { s.visit_children_with(self); - self.add(COMMON_ITERATORS) + self.may_inject_global(COMMON_ITERATORS) } fn visit_function(&mut self, f: &Function) { f.visit_children_with(self); if f.is_async { - self.add(PROMISE_DEPENDENCIES) + self.may_inject_global(PROMISE_DEPENDENCIES) } } @@ -262,14 +260,12 @@ impl Visit for UsageVisitor { } } - // TODO: https://github.com/babel/babel/blob/00758308/packages/babel-preset-env/src/polyfills/corejs3/usage-plugin.js#L198-L206 - /// `yield*` fn visit_yield_expr(&mut self, e: &YieldExpr) { e.visit_children_with(self); if e.delegate { - self.add(COMMON_ITERATORS) + self.may_inject_global(COMMON_ITERATORS) } } } diff --git a/crates/swc_ecma_preset_env/src/util.rs b/crates/swc_ecma_preset_env/src/util.rs index c8bd46e8de2..8191669140e 100644 --- a/crates/swc_ecma_preset_env/src/util.rs +++ b/crates/swc_ecma_preset_env/src/util.rs @@ -1,3 +1,32 @@ +use rustc_hash::FxHashMap; + +pub(crate) type ObjectMap = FxHashMap<&'static str, T>; +pub(crate) type ObjectMap2 = ObjectMap>; + +pub(crate) fn descriptor( + pure: Option<&'static str>, + global: &'static [&'static str], + name: Option<&'static str>, + exclude: &'static [&'static str], +) -> CoreJSPolyfillDescriptor { + let name = name.unwrap_or_else(|| global[0]); + + CoreJSPolyfillDescriptor { + pure, + global, + name, + exclude, + } +} + +#[derive(Debug, Clone, Copy)] +pub(crate) struct CoreJSPolyfillDescriptor { + pub pure: Option<&'static str>, + pub global: &'static [&'static str], + pub name: &'static str, + pub exclude: &'static [&'static str], +} + macro_rules! val { (& $v:expr) => { &$v @@ -7,6 +36,428 @@ macro_rules! val { }; } +macro_rules! expand_array_like { + ($name:ident) => {{ + $name + }}; + ($lit:literal) => {{ + [$lit] + }}; + + // An array with a single item + ([$first:tt]) => {{ + expand_array_like!($first) + }}; + + ([$($tt:tt)*]) => {{ + expand_array_like!(@ARRAY, All(&[]), Wip(), Rest($($tt)*)) + }}; + + // Eat string literal as much as we can, and create a single array literal from them. + (@ARRAY, All($all:expr), Wip($($s:literal)*), Rest($first:literal, $($rest:tt)*)) => {{ + expand_array_like!(@ARRAY, All($all), Wip($($s)* $first), Rest($($rest)*)) + }}; + + (@ARRAY, All($all:expr), Wip($($s:literal)*), Rest($first:literal)) => {{ + expand_array_like!(@ARRAY, All($all), Wip($($s)* $first), Rest()) + }}; + + // We need to stop eating string literals. + (@ARRAY, All($all:expr), Wip($($s:literal)*), Rest($first:ident, $($rest:tt)*)) => {{ + static PREV: &[&str]= &[$($s),*]; + + dynamic_concat($all, dynamic_concat(PREV, $first)) + }}; + + (@ARRAY, All($all:expr), Wip($($s:literal)*), Rest($first:ident)) => {{ + static PREV: &[&str]= &[$($s),*]; + + dynamic_concat($all, dynamic_concat(PREV, $first)) + }}; + + + // Done + (@ARRAY, All($all:expr), Wip($($s:literal)*), Rest()) => {{ + static CUR_LIT: &[&str]= &[$($s),*]; + + dynamic_concat($all, CUR_LIT) + }}; +} + +/// Calls [`descriptor`]. +macro_rules! define_descriptor { + + ( + $pure:literal, + [$($global:tt)*] + ) => {{ + define_descriptor!(@Done, Some($pure), &expand_array_like!([$($global)*]), None, &[]) + }}; + + ( + null, + [$($global:tt)*] + ) => {{ + define_descriptor!(@Done, None, &expand_array_like!([$($global)*]), None, &[]) + }}; + + + ( + null, + $global:ident + ) => {{ + define_descriptor!(@Done, None, &expand_array_like!($global), None, &[]) + }}; + + ( + $pure:literal, + $global:ident + ) => {{ + define_descriptor!(@Done, Some($pure), &expand_array_like!($global), None, &[]) + }}; + + ( + $pure:literal, + $global:ident, + $first:tt + ) => {{ + define_descriptor!(@Done, Some($pure), &expand_array_like!($($global)*), Some($first), &[]) + }}; + + + ( + $pure:literal, + [$($global:tt)*], + $first:literal + ) => {{ + define_descriptor!(@Done, Some($pure), &expand_array_like!([$($global)*]), Some($first), &[]) + }}; + + ( + $pure:literal, + [$($global:tt)*], + None, + $exclude:tt + ) => {{ + define_descriptor!(@Done, Some($pure), &expand_array_like!([$($global)*]), None, &$exclude) + }}; + + // @Indirect: No need to distinguish `$pure`. + ( + @Done, + $pure:expr, + $global:expr, + $name:expr, + $exclude:expr + ) => {{ + $crate::util::descriptor($pure, $global, $name, $exclude) + }}; +} + +macro_rules! lazy_map { + ($($tt:tt)*) => {{ + Lazy::new(|| map!($($tt)*)) + }}; +} + +macro_rules! map { + ( + Map { + $($rest:tt)+ + } + ) => {{ + map!(@Key, Map {}, Rest {$($rest)*}) + }}; + + ( + @Key, + Map { + $($i:ident : $e:expr,)* + }, + Rest { + $ni:ident : $($rest:tt)+ + } + ) => {{ + map!( + @Value, + Map { + $( + $i : $e, + )* + }, + Rest { + $($rest)* + }, + Wip { + $ni + } + ) + }}; + + ( + @Value, + Map { + $($i:ident : $e:expr,)* + }, + Rest { + [$($v:tt)*], $($rest:tt)* + }, + Wip { + $ni:ident + } + ) => { + map!(@Key, Map { + $( + $i : $e, + )* + $ni : val!(&[$($v)*]), + }, Rest {$($rest)*}) + }; + + ( + @Value, + Map { + $($i:ident : $e:expr,)* + }, + Rest { + &[$($v:tt)*], $($rest:tt)* + }, + Wip { + $ni:ident + } + ) => { + map!(@Key, Map { + $( + $i : $e, + )* + $ni : val!(&[$($v)*]), + }, + Rest { + $($rest)* + }) + }; + + ( + @Value, + Map { + $($i:ident : $e:expr,)* + }, + Rest { + $v:literal, $($rest:tt)* + }, + Wip { + $ni:ident + } + ) => { + map!(@Key, Map { + $( + $i : $e, + )* + $ni : &[$v], + }, + Rest { + $($rest)* + }) + }; + + ( + @Value, + Map { + $($i:ident : $e:expr,)* + }, + Rest { + $v:literal $($rest:tt)* + }, + Wip { + $ni:ident + } + ) => { + map!(@Key, Map { + $( + $i : $e, + )* + $ni : &[$v], + }, + Rest { + $($rest)* + }) + }; + + ( + @Value, + Map { + $($i:ident : $e:expr,)* + }, + Rest { + &$v:ident, $($rest:tt)* + }, + Wip { + $ni:ident + } + ) => { + map!(@Key, Map { + $( + $i : $e, + )* + $ni : $v, + }, + Rest { + $($rest)* + }) + }; + + + ( + @Value, + Map { + $($i:ident : $e:expr,)* + }, + Rest { + Map { $($m:tt)* }, $($rest:tt)* + }, + Wip { + $ni:ident + } + ) => { + map!( + @Key, + Map { + $( + $i : $e, + )* + $ni : map!(Map { $($m)* }), + }, + Rest { + $($rest)* + } + ) + }; + + + ( + @Value, + Map { + $($i:ident : $e:expr,)* + }, + Rest { + $v:ident, $($rest:tt)* + }, + Wip { + $ni:ident + } + ) => { + map!( + @Key, + Map { + $( + $i : $e, + )* + $ni : $v, + }, + Rest { + $($rest)* + } + ) + }; + + ( + @Value, + Map { + $($i:ident : $e:expr,)* + }, + Rest { + *$v:ident, $($rest:tt)* + }, + Wip { + $ni:ident + } + ) => { + map!( + @Key, + Map { + $( + $i : $e, + )* + $ni : (*$v).clone(), + }, + Rest { + $($rest)* + } + ) + }; + + + ( + @Value, + Map { + $($i:ident : $e:expr,)* + }, + Rest { + define($($args:tt)*), $($rest:tt)* + }, + Wip { + $ni:ident + } + ) => { + map!( + @Key, + Map { + $( + $i : $e, + )* + $ni : define_descriptor!($($args)*), + }, + Rest { + $($rest)* + } + ) + }; + + ( + @Value, + Map { + $($i:ident : $e:expr,)* + }, + Rest { + $callee:ident($($args:tt)*), $($rest:tt)* + }, + Wip { + $ni:ident + } + ) => { + map!( + @Key, + Map { + $( + $i : $e, + )* + $ni : $callee($($args)*), + }, + Rest { + $($rest)* + } + ) + }; + + + // Done + ( + @Key, + Map { + $($i:ident : $e:expr,)* + }, + Rest {} + ) => {{ + let mut map = ObjectMap::default(); + + $( + map.insert(stringify!($i), $e); + )* + + map + }}; +} + macro_rules! data_map { ( Map {