From 736cdf64acfc4ca57028eb0399b4052bf65aa6be Mon Sep 17 00:00:00 2001 From: X Date: Thu, 27 Jun 2024 22:25:21 +0800 Subject: [PATCH] Update npm polyfills --- server/build.go | 44 +++++++++++++++---- server/build_resolver.go | 20 +++++---- server/embed/polyfills/npm_array-every.js | 2 + .../polyfills/npm_array.prototype.find.js | 1 + .../embed/polyfills/npm_define-properties.js | 1 + server/embed/polyfills/npm_define-property.js | 1 + .../embed/polyfills/npm_es-define-property.js | 1 + server/embed/polyfills/npm_filter-array.js | 1 + server/embed/polyfills/npm_for-each.js | 9 ++++ server/embed/polyfills/npm_has-own-prop.js | 1 + server/embed/polyfills/npm_has-own.js | 3 +- .../polyfills/npm_has-property-descriptors.js | 1 + server/embed/polyfills/npm_has-tostringtag.js | 1 + server/embed/polyfills/npm_hasown.js | 1 + server/embed/polyfills/npm_index-of.js | 1 + server/embed/polyfills/npm_is-even.js | 1 + server/embed/polyfills/npm_is-nan.js | 1 + server/embed/polyfills/npm_is-number.js | 1 + server/embed/polyfills/npm_is-odd.js | 1 + server/embed/polyfills/npm_is-regexp.js | 1 + server/embed/polyfills/npm_is-string.js | 1 + server/embed/polyfills/npm_left-pad.js | 1 + server/embed/polyfills/npm_object-is.js | 1 + server/embed/polyfills/npm_object-keys.js | 1 + server/embed/polyfills/npm_object.entries.js | 1 + server/embed/polyfills/npm_object.values.js | 1 + server/embed/polyfills/npm_pad-left.js | 1 + .../polyfills/npm_regexp.prototype.flags.js | 1 + server/nodejs.go | 2 +- test/esm-worker/test.ts | 2 +- 30 files changed, 84 insertions(+), 21 deletions(-) create mode 100644 server/embed/polyfills/npm_array-every.js create mode 100644 server/embed/polyfills/npm_array.prototype.find.js create mode 100644 server/embed/polyfills/npm_define-properties.js create mode 100644 server/embed/polyfills/npm_define-property.js create mode 100644 server/embed/polyfills/npm_es-define-property.js create mode 100644 server/embed/polyfills/npm_filter-array.js create mode 100644 server/embed/polyfills/npm_for-each.js create mode 100644 server/embed/polyfills/npm_has-own-prop.js create mode 100644 server/embed/polyfills/npm_has-property-descriptors.js create mode 100644 server/embed/polyfills/npm_has-tostringtag.js create mode 100644 server/embed/polyfills/npm_hasown.js create mode 100644 server/embed/polyfills/npm_index-of.js create mode 100644 server/embed/polyfills/npm_is-even.js create mode 100644 server/embed/polyfills/npm_is-nan.js create mode 100644 server/embed/polyfills/npm_is-number.js create mode 100644 server/embed/polyfills/npm_is-odd.js create mode 100644 server/embed/polyfills/npm_is-regexp.js create mode 100644 server/embed/polyfills/npm_is-string.js create mode 100644 server/embed/polyfills/npm_left-pad.js create mode 100644 server/embed/polyfills/npm_object-is.js create mode 100644 server/embed/polyfills/npm_object-keys.js create mode 100644 server/embed/polyfills/npm_object.entries.js create mode 100644 server/embed/polyfills/npm_object.values.js create mode 100644 server/embed/polyfills/npm_pad-left.js create mode 100644 server/embed/polyfills/npm_regexp.prototype.flags.js diff --git a/server/build.go b/server/build.go index 2294bf637..7ac7568db 100644 --- a/server/build.go +++ b/server/build.go @@ -427,6 +427,17 @@ func (ctx *BuildContext) buildModule() (result BuildResult, err error) { } } + if specifier != "node-fetch" && args.Kind != api.ResolveJSRequireCall && args.Kind != api.ResolveJSRequireResolve { + data, err := embedFS.ReadFile(("server/embed/polyfills/npm_" + specifier + ".js")) + if err == nil { + return api.OnResolveResult{ + Path: args.Path, + PluginData: data, + Namespace: "purge-polyfill", + }, nil + } + } + // resolve specifier with package `browser` field if !isRelativeSpecifier(specifier) && len(ctx.pkgJson.Browser) > 0 && ctx.isBrowserTarget() { if name, ok := ctx.pkgJson.Browser[specifier]; ok { @@ -729,21 +740,21 @@ func (ctx *BuildContext) buildModule() (result BuildResult, err error) { }, ) - // for wasm module exclude + // purge polyfill build.OnLoad( - api.OnLoadOptions{Filter: ".*", Namespace: "wasm"}, + api.OnLoadOptions{Filter: ".*", Namespace: "purge-polyfill"}, func(args api.OnLoadArgs) (ret api.OnLoadResult, err error) { - wasm, err := os.ReadFile(args.Path) - if err != nil { + data, ok := args.PluginData.([]byte) + if !ok { + err = fmt.Errorf("purge-polyfill: invalid plugin data") return } - wasm64 := base64.StdEncoding.EncodeToString(wasm) - code := fmt.Sprintf("export default Uint8Array.from(atob('%s'), c => c.charCodeAt(0))", wasm64) - return api.OnLoadResult{Contents: &code, Loader: api.LoaderJS}, nil + contents := string(data) + return api.OnLoadResult{Contents: &contents, Loader: api.LoaderJS}, nil }, ) - // for browser exclude + // browser exclude build.OnLoad( api.OnLoadOptions{Filter: ".*", Namespace: "browser-exclude"}, func(args api.OnLoadArgs) (ret api.OnLoadResult, err error) { @@ -757,6 +768,21 @@ func (ctx *BuildContext) buildModule() (result BuildResult, err error) { }, ) + // wasm module exclude + build.OnLoad( + api.OnLoadOptions{Filter: ".*", Namespace: "wasm"}, + func(args api.OnLoadArgs) (ret api.OnLoadResult, err error) { + wasm, err := os.ReadFile(args.Path) + if err != nil { + return + } + wasm64 := base64.StdEncoding.EncodeToString(wasm) + code := fmt.Sprintf("export default Uint8Array.from(atob('%s'), c => c.charCodeAt(0))", wasm64) + return api.OnLoadResult{Contents: &code, Loader: api.LoaderJS}, nil + }, + ) + + // resolve `__filename` and `__dirname` build.OnLoad( api.OnLoadOptions{Filter: "\\.c?js$"}, func(args api.OnLoadArgs) (ret api.OnLoadResult, err error) { @@ -833,6 +859,7 @@ func (ctx *BuildContext) buildModule() (result BuildResult, err error) { return api.OnLoadResult{Contents: &js, Loader: api.LoaderJS}, nil }, ) + }, } @@ -960,7 +987,6 @@ rebuild: } } err = errors.New("esbuild: " + msg) - fmt.Println(ret.Errors[0].Location) return } diff --git a/server/build_resolver.go b/server/build_resolver.go index f464a1660..6492529de 100644 --- a/server/build_resolver.go +++ b/server/build_resolver.go @@ -775,14 +775,18 @@ func (ctx *BuildContext) resolveExternalModule(specifier string, kind api.Resolv } // replace some npm polyfills with native APIs - if specifier == "node-fetch" && ctx.target != "node" { - resolvedPath = "/npm_node-fetch.js" - return - } - data, err := embedFS.ReadFile(("server/embed/polyfills/npm_" + specifier + ".js")) - if err == nil { - resolvedPath = fmt.Sprintf("data:application/javascript;base64,%s", base64.StdEncoding.EncodeToString(data)) - return + + if specifier == "node-fetch" { + if ctx.target != "node" { + resolvedPath = "/npm_node-fetch.js" + return + } + } else { + data, err := embedFS.ReadFile(("server/embed/polyfills/npm_" + specifier + ".js")) + if err == nil { + resolvedPath = fmt.Sprintf("data:text/javascript;base64,%s", base64.StdEncoding.EncodeToString(data)) + return + } } // common npm dependency diff --git a/server/embed/polyfills/npm_array-every.js b/server/embed/polyfills/npm_array-every.js new file mode 100644 index 000000000..495d6dd12 --- /dev/null +++ b/server/embed/polyfills/npm_array-every.js @@ -0,0 +1,2 @@ +export const every = (a, p, t) => a.every(p, t); +export default every; diff --git a/server/embed/polyfills/npm_array.prototype.find.js b/server/embed/polyfills/npm_array.prototype.find.js new file mode 100644 index 000000000..0d2ffc8bd --- /dev/null +++ b/server/embed/polyfills/npm_array.prototype.find.js @@ -0,0 +1 @@ +export default (a, predicate, thisArg) => a.find(predicate, thisArg); diff --git a/server/embed/polyfills/npm_define-properties.js b/server/embed/polyfills/npm_define-properties.js new file mode 100644 index 000000000..545bcfe99 --- /dev/null +++ b/server/embed/polyfills/npm_define-properties.js @@ -0,0 +1 @@ +export default Object.defineProperties; diff --git a/server/embed/polyfills/npm_define-property.js b/server/embed/polyfills/npm_define-property.js new file mode 100644 index 000000000..d07878600 --- /dev/null +++ b/server/embed/polyfills/npm_define-property.js @@ -0,0 +1 @@ +export default Object.defineProperty; diff --git a/server/embed/polyfills/npm_es-define-property.js b/server/embed/polyfills/npm_es-define-property.js new file mode 100644 index 000000000..d07878600 --- /dev/null +++ b/server/embed/polyfills/npm_es-define-property.js @@ -0,0 +1 @@ +export default Object.defineProperty; diff --git a/server/embed/polyfills/npm_filter-array.js b/server/embed/polyfills/npm_filter-array.js new file mode 100644 index 000000000..950e6ff75 --- /dev/null +++ b/server/embed/polyfills/npm_filter-array.js @@ -0,0 +1 @@ +export default (a, predicate, thisArg) => a.filter(predicate, thisArg); diff --git a/server/embed/polyfills/npm_for-each.js b/server/embed/polyfills/npm_for-each.js new file mode 100644 index 000000000..40bd1032c --- /dev/null +++ b/server/embed/polyfills/npm_for-each.js @@ -0,0 +1,9 @@ +export default (v, cb) => { + if (Array.isArray(v)) { + v.forEach(cb); + } else if (v && typeof v === "object") { + for (const k in v) { + cb(v[k], k, v); + } + } +}; diff --git a/server/embed/polyfills/npm_has-own-prop.js b/server/embed/polyfills/npm_has-own-prop.js new file mode 100644 index 000000000..bec3b4916 --- /dev/null +++ b/server/embed/polyfills/npm_has-own-prop.js @@ -0,0 +1 @@ +export default (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop); diff --git a/server/embed/polyfills/npm_has-own.js b/server/embed/polyfills/npm_has-own.js index bc578aace..656d48a42 100644 --- a/server/embed/polyfills/npm_has-own.js +++ b/server/embed/polyfills/npm_has-own.js @@ -1,2 +1 @@ -const hasOwn = Object.prototype.hasOwnProperty; -export default Object.hasOwn ?? ((o, p) => hasOwn.call(o, p)); +export default Object.hasOwn ?? ((o, p) => Object.prototype.hasOwnProperty.call(o, p)); diff --git a/server/embed/polyfills/npm_has-property-descriptors.js b/server/embed/polyfills/npm_has-property-descriptors.js new file mode 100644 index 000000000..3c72b2d38 --- /dev/null +++ b/server/embed/polyfills/npm_has-property-descriptors.js @@ -0,0 +1 @@ +export default () => true; diff --git a/server/embed/polyfills/npm_has-tostringtag.js b/server/embed/polyfills/npm_has-tostringtag.js new file mode 100644 index 000000000..bc03a785d --- /dev/null +++ b/server/embed/polyfills/npm_has-tostringtag.js @@ -0,0 +1 @@ +export default () => typeof Symbol.toStringTag === "symbol"; diff --git a/server/embed/polyfills/npm_hasown.js b/server/embed/polyfills/npm_hasown.js new file mode 100644 index 000000000..656d48a42 --- /dev/null +++ b/server/embed/polyfills/npm_hasown.js @@ -0,0 +1 @@ +export default Object.hasOwn ?? ((o, p) => Object.prototype.hasOwnProperty.call(o, p)); diff --git a/server/embed/polyfills/npm_index-of.js b/server/embed/polyfills/npm_index-of.js new file mode 100644 index 000000000..33a80bfab --- /dev/null +++ b/server/embed/polyfills/npm_index-of.js @@ -0,0 +1 @@ +export default (a, searchElement, start) => a.indexOf(searchElement, start); diff --git a/server/embed/polyfills/npm_is-even.js b/server/embed/polyfills/npm_is-even.js new file mode 100644 index 000000000..33883b45d --- /dev/null +++ b/server/embed/polyfills/npm_is-even.js @@ -0,0 +1 @@ +export default (n) => (n % 2) === 0; diff --git a/server/embed/polyfills/npm_is-nan.js b/server/embed/polyfills/npm_is-nan.js new file mode 100644 index 000000000..3cceafd24 --- /dev/null +++ b/server/embed/polyfills/npm_is-nan.js @@ -0,0 +1 @@ +export default Number.isNaN; diff --git a/server/embed/polyfills/npm_is-number.js b/server/embed/polyfills/npm_is-number.js new file mode 100644 index 000000000..2d7545ab3 --- /dev/null +++ b/server/embed/polyfills/npm_is-number.js @@ -0,0 +1 @@ +export default (v) => typeof v === "number"; diff --git a/server/embed/polyfills/npm_is-odd.js b/server/embed/polyfills/npm_is-odd.js new file mode 100644 index 000000000..ba7a8e9d7 --- /dev/null +++ b/server/embed/polyfills/npm_is-odd.js @@ -0,0 +1 @@ +export default (n) => (n % 2) === 1; diff --git a/server/embed/polyfills/npm_is-regexp.js b/server/embed/polyfills/npm_is-regexp.js new file mode 100644 index 000000000..9c7a61c8d --- /dev/null +++ b/server/embed/polyfills/npm_is-regexp.js @@ -0,0 +1 @@ +export default (v) => v instanceof RegExp; diff --git a/server/embed/polyfills/npm_is-string.js b/server/embed/polyfills/npm_is-string.js new file mode 100644 index 000000000..17e25f933 --- /dev/null +++ b/server/embed/polyfills/npm_is-string.js @@ -0,0 +1 @@ +export default (v) => typeof v === "string"; diff --git a/server/embed/polyfills/npm_left-pad.js b/server/embed/polyfills/npm_left-pad.js new file mode 100644 index 000000000..5c337a431 --- /dev/null +++ b/server/embed/polyfills/npm_left-pad.js @@ -0,0 +1 @@ +export default (s, l, c) => s.padStart(l, c); diff --git a/server/embed/polyfills/npm_object-is.js b/server/embed/polyfills/npm_object-is.js new file mode 100644 index 000000000..5721c8185 --- /dev/null +++ b/server/embed/polyfills/npm_object-is.js @@ -0,0 +1 @@ +export default Object.is; diff --git a/server/embed/polyfills/npm_object-keys.js b/server/embed/polyfills/npm_object-keys.js new file mode 100644 index 000000000..4583a8faa --- /dev/null +++ b/server/embed/polyfills/npm_object-keys.js @@ -0,0 +1 @@ +export default Object.keys; diff --git a/server/embed/polyfills/npm_object.entries.js b/server/embed/polyfills/npm_object.entries.js new file mode 100644 index 000000000..2ecd723c3 --- /dev/null +++ b/server/embed/polyfills/npm_object.entries.js @@ -0,0 +1 @@ +export default Object.entries; diff --git a/server/embed/polyfills/npm_object.values.js b/server/embed/polyfills/npm_object.values.js new file mode 100644 index 000000000..fcb5d39ec --- /dev/null +++ b/server/embed/polyfills/npm_object.values.js @@ -0,0 +1 @@ +export default Object.values; diff --git a/server/embed/polyfills/npm_pad-left.js b/server/embed/polyfills/npm_pad-left.js new file mode 100644 index 000000000..5c337a431 --- /dev/null +++ b/server/embed/polyfills/npm_pad-left.js @@ -0,0 +1 @@ +export default (s, l, c) => s.padStart(l, c); diff --git a/server/embed/polyfills/npm_regexp.prototype.flags.js b/server/embed/polyfills/npm_regexp.prototype.flags.js new file mode 100644 index 000000000..9732588e3 --- /dev/null +++ b/server/embed/polyfills/npm_regexp.prototype.flags.js @@ -0,0 +1 @@ +export default (reg) => reg.flags; diff --git a/server/nodejs.go b/server/nodejs.go index 5752de080..23e7122c5 100644 --- a/server/nodejs.go +++ b/server/nodejs.go @@ -17,8 +17,8 @@ import ( const ( nodejsMinVersion = 22 - pnpmMinVersion = "9.0.0" nodeTypesVersion = "20.14.4" + pnpmMinVersion = "9.0.0" ) var nodejsInternalModules = map[string]bool{ diff --git a/test/esm-worker/test.ts b/test/esm-worker/test.ts index 63f3d57c6..e7dafc5f5 100644 --- a/test/esm-worker/test.ts +++ b/test/esm-worker/test.ts @@ -289,7 +289,7 @@ Deno.test("esm-worker", { sanitizeOps: false, sanitizeResources: false }, async assertEquals(res7.status, 200); assertStringIncludes( await res7.text(), - `"data:application/javascript;base64,ZXhwb3J0IGRlZmF1bHQgT2JqZWN0LmFzc2lnbjsK"`, + `"data:text/javascript;base64,ZXhwb3J0IGRlZmF1bHQgT2JqZWN0LmFzc2lnbjsK"`, ); const res8 = await fetch(`${workerOrigin}/react-dom@18.2.0?external=react`);