From 3cd7f2e312ffb559c271fa6267bcb0bb9267892e Mon Sep 17 00:00:00 2001 From: Nick Gerleman Date: Thu, 19 Oct 2023 19:10:19 -0700 Subject: [PATCH] Fix wrapAssembly extensions not getting rewritten --- javascript/src/wrapAssembly.js | 147 ------------------ .../{wrapAssembly.d.ts => wrapAssembly.ts} | 145 ++++++++++++++++- 2 files changed, 139 insertions(+), 153 deletions(-) delete mode 100644 javascript/src/wrapAssembly.js rename javascript/src/{wrapAssembly.d.ts => wrapAssembly.ts} (55%) diff --git a/javascript/src/wrapAssembly.js b/javascript/src/wrapAssembly.js deleted file mode 100644 index eeeb8c30e0..0000000000 --- a/javascript/src/wrapAssembly.js +++ /dev/null @@ -1,147 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @format - */ - -import {Unit, Direction} from './generated/YGEnums.ts'; -import YGEnums from './generated/YGEnums.ts'; - -export default function wrapAssembly(lib) { - function patch(prototype, name, fn) { - const original = prototype[name]; - - prototype[name] = function (...args) { - return fn.call(this, original, ...args); - }; - } - - for (const fnName of [ - 'setPosition', - 'setMargin', - 'setFlexBasis', - 'setWidth', - 'setHeight', - 'setMinWidth', - 'setMinHeight', - 'setMaxWidth', - 'setMaxHeight', - 'setPadding', - ]) { - const methods = { - [Unit.Point]: lib.Node.prototype[fnName], - [Unit.Percent]: lib.Node.prototype[`${fnName}Percent`], - [Unit.Auto]: lib.Node.prototype[`${fnName}Auto`], - }; - - patch(lib.Node.prototype, fnName, function (original, ...args) { - // We patch all these functions to add support for the following calls: - // .setWidth(100) / .setWidth("100%") / .setWidth(.getWidth()) / .setWidth("auto") - - const value = args.pop(); - let unit, asNumber; - - if (value === 'auto') { - unit = Unit.Auto; - asNumber = undefined; - } else if (typeof value === 'object') { - unit = value.unit; - asNumber = value.valueOf(); - } else { - unit = - typeof value === 'string' && value.endsWith('%') - ? Unit.Percent - : Unit.Point; - asNumber = parseFloat(value); - if (!Number.isNaN(value) && Number.isNaN(asNumber)) { - throw new Error(`Invalid value ${value} for ${fnName}`); - } - } - - if (!methods[unit]) - throw new Error( - `Failed to execute "${fnName}": Unsupported unit '${value}'`, - ); - - if (asNumber !== undefined) { - return methods[unit].call(this, ...args, asNumber); - } else { - return methods[unit].call(this, ...args); - } - }); - } - - function wrapMeasureFunction(measureFunction) { - return lib.MeasureCallback.implement({ - measure: (...args) => { - const {width, height} = measureFunction(...args); - return { - width: width ?? NaN, - height: height ?? NaN, - }; - }, - }); - } - - patch(lib.Node.prototype, 'setMeasureFunc', function (original, measureFunc) { - // This patch is just a convenience patch, since it helps write more - // idiomatic source code (such as .setMeasureFunc(null)) - if (measureFunc) { - return original.call(this, wrapMeasureFunction(measureFunc)); - } else { - return this.unsetMeasureFunc(); - } - }); - - function wrapDirtiedFunc(dirtiedFunction) { - return lib.DirtiedCallback.implement({dirtied: dirtiedFunction}); - } - - patch(lib.Node.prototype, 'setDirtiedFunc', function (original, dirtiedFunc) { - original.call(this, wrapDirtiedFunc(dirtiedFunc)); - }); - - patch(lib.Config.prototype, 'free', function () { - // Since we handle the memory allocation ourselves (via lib.Config.create), - // we also need to handle the deallocation - lib.Config.destroy(this); - }); - - patch(lib.Node, 'create', (_, config) => { - // We decide the constructor we want to call depending on the parameters - return config - ? lib.Node.createWithConfig(config) - : lib.Node.createDefault(); - }); - - patch(lib.Node.prototype, 'free', function () { - // Since we handle the memory allocation ourselves (via lib.Node.create), - // we also need to handle the deallocation - lib.Node.destroy(this); - }); - - patch(lib.Node.prototype, 'freeRecursive', function () { - for (let t = 0, T = this.getChildCount(); t < T; ++t) { - this.getChild(0).freeRecursive(); - } - this.free(); - }); - - patch( - lib.Node.prototype, - 'calculateLayout', - function (original, width = NaN, height = NaN, direction = Direction.LTR) { - // Just a small patch to add support for the function default parameters - return original.call(this, width, height, direction); - }, - ); - - return { - Config: lib.Config, - Node: lib.Node, - ...YGEnums, - }; -} diff --git a/javascript/src/wrapAssembly.d.ts b/javascript/src/wrapAssembly.ts similarity index 55% rename from javascript/src/wrapAssembly.d.ts rename to javascript/src/wrapAssembly.ts index b6e2cbab3c..0d55a2c6bf 100644 --- a/javascript/src/wrapAssembly.d.ts +++ b/javascript/src/wrapAssembly.ts @@ -6,10 +6,13 @@ * * @format */ +// @ts-nocheck + +import {Unit, Direction} from './generated/YGEnums.ts'; +import YGEnums from './generated/YGEnums.ts'; import type { Align, - Direction, Display, Edge, Errata, @@ -20,12 +23,9 @@ import type { MeasureMode, Overflow, PositionType, - Unit, Wrap, } from './generated/YGEnums'; -import YGEnums from './generated/YGEnums'; - type Layout = { left: number; right: number; @@ -179,5 +179,138 @@ export type Yoga = { }; } & typeof YGEnums; -declare const wrapAsm: (assembly: unknown) => Yoga; -export default wrapAsm; +export default function wrapAssembly(lib: unknown): Yoga { + function patch(prototype, name, fn) { + const original = prototype[name]; + + prototype[name] = function (...args) { + return fn.call(this, original, ...args); + }; + } + + for (const fnName of [ + 'setPosition', + 'setMargin', + 'setFlexBasis', + 'setWidth', + 'setHeight', + 'setMinWidth', + 'setMinHeight', + 'setMaxWidth', + 'setMaxHeight', + 'setPadding', + ]) { + const methods = { + [Unit.Point]: lib.Node.prototype[fnName], + [Unit.Percent]: lib.Node.prototype[`${fnName}Percent`], + [Unit.Auto]: lib.Node.prototype[`${fnName}Auto`], + }; + + patch(lib.Node.prototype, fnName, function (original, ...args) { + // We patch all these functions to add support for the following calls: + // .setWidth(100) / .setWidth("100%") / .setWidth(.getWidth()) / .setWidth("auto") + + const value = args.pop(); + let unit, asNumber; + + if (value === 'auto') { + unit = Unit.Auto; + asNumber = undefined; + } else if (typeof value === 'object') { + unit = value.unit; + asNumber = value.valueOf(); + } else { + unit = + typeof value === 'string' && value.endsWith('%') + ? Unit.Percent + : Unit.Point; + asNumber = parseFloat(value); + if (!Number.isNaN(value) && Number.isNaN(asNumber)) { + throw new Error(`Invalid value ${value} for ${fnName}`); + } + } + + if (!methods[unit]) + throw new Error( + `Failed to execute "${fnName}": Unsupported unit '${value}'`, + ); + + if (asNumber !== undefined) { + return methods[unit].call(this, ...args, asNumber); + } else { + return methods[unit].call(this, ...args); + } + }); + } + + function wrapMeasureFunction(measureFunction) { + return lib.MeasureCallback.implement({ + measure: (...args) => { + const {width, height} = measureFunction(...args); + return { + width: width ?? NaN, + height: height ?? NaN, + }; + }, + }); + } + + patch(lib.Node.prototype, 'setMeasureFunc', function (original, measureFunc) { + // This patch is just a convenience patch, since it helps write more + // idiomatic source code (such as .setMeasureFunc(null)) + if (measureFunc) { + return original.call(this, wrapMeasureFunction(measureFunc)); + } else { + return this.unsetMeasureFunc(); + } + }); + + function wrapDirtiedFunc(dirtiedFunction) { + return lib.DirtiedCallback.implement({dirtied: dirtiedFunction}); + } + + patch(lib.Node.prototype, 'setDirtiedFunc', function (original, dirtiedFunc) { + original.call(this, wrapDirtiedFunc(dirtiedFunc)); + }); + + patch(lib.Config.prototype, 'free', function () { + // Since we handle the memory allocation ourselves (via lib.Config.create), + // we also need to handle the deallocation + lib.Config.destroy(this); + }); + + patch(lib.Node, 'create', (_, config) => { + // We decide the constructor we want to call depending on the parameters + return config + ? lib.Node.createWithConfig(config) + : lib.Node.createDefault(); + }); + + patch(lib.Node.prototype, 'free', function () { + // Since we handle the memory allocation ourselves (via lib.Node.create), + // we also need to handle the deallocation + lib.Node.destroy(this); + }); + + patch(lib.Node.prototype, 'freeRecursive', function () { + for (let t = 0, T = this.getChildCount(); t < T; ++t) { + this.getChild(0).freeRecursive(); + } + this.free(); + }); + + patch( + lib.Node.prototype, + 'calculateLayout', + function (original, width = NaN, height = NaN, direction = Direction.LTR) { + // Just a small patch to add support for the function default parameters + return original.call(this, width, height, direction); + }, + ); + + return { + Config: lib.Config, + Node: lib.Node, + ...YGEnums, + }; +}