diff --git a/javascript/.eslintrc.js b/javascript/.eslintrc.js index 2baa5f0f..a350868b 100644 --- a/javascript/.eslintrc.js +++ b/javascript/.eslintrc.js @@ -7,20 +7,20 @@ * @format */ -const path = require("path"); +const path = require('path'); module.exports = { root: true, - ignorePatterns: ["dist/**", "tests/generated/**"], - extends: ["eslint:recommended", "plugin:prettier/recommended"], - plugins: ["prettier"], + ignorePatterns: ['dist/**', 'tests/generated/**'], + extends: ['eslint:recommended', 'plugin:prettier/recommended'], + plugins: ['prettier'], rules: { - "no-var": "error", - "prefer-arrow-callback": "error", - "prefer-const": "error", - "prefer-object-spread": "error", - "prefer-spread": "error", - "require-await": "error", + 'no-var': 'error', + 'prefer-arrow-callback': 'error', + 'prefer-const': 'error', + 'prefer-object-spread': 'error', + 'prefer-spread': 'error', + 'require-await': 'error', }, env: { commonjs: true, @@ -28,44 +28,44 @@ module.exports = { }, overrides: [ { - files: ["**/*.js"], - parser: "@babel/eslint-parser", + files: ['**/*.js'], + parser: '@babel/eslint-parser', parserOptions: { babelOptions: { - configFile: path.join(__dirname, ".babelrc.js"), + configFile: path.join(__dirname, '.babelrc.js'), }, }, }, { - files: ["**/*.ts"], - extends: ["plugin:@typescript-eslint/recommended"], - parser: "@typescript-eslint/parser", + files: ['**/*.ts'], + extends: ['plugin:@typescript-eslint/recommended'], + parser: '@typescript-eslint/parser', parserOptions: { - project: path.join(__dirname, "tsconfig.json"), + project: path.join(__dirname, 'tsconfig.json'), }, - plugins: ["@typescript-eslint"], + plugins: ['@typescript-eslint'], rules: { - "@typescript-eslint/no-var-requires": "off", + '@typescript-eslint/no-var-requires': 'off', }, }, { - files: ["**/.eslintrc.js", "**/just.config.js"], + files: ['**/.eslintrc.js', '**/just.config.js'], env: { node: true, }, }, { - files: ["jest.*", "tests/**"], + files: ['jest.*', 'tests/**'], env: { node: true, }, - extends: ["plugin:jest/recommended"], + extends: ['plugin:jest/recommended'], globals: { - getMeasureCounter: "writable", - getMeasureCounterMax: "writable", - getMeasureCounterMin: "writable", - Yoga: "writable", - YGBENCHMARK: "writable", + getMeasureCounter: 'writable', + getMeasureCounterMax: 'writable', + getMeasureCounterMin: 'writable', + Yoga: 'writable', + YGBENCHMARK: 'writable', }, }, ], diff --git a/javascript/.gitignore b/javascript/.gitignore index 29751e5c..198af7f7 100644 --- a/javascript/.gitignore +++ b/javascript/.gitignore @@ -1,3 +1,4 @@ +/binaries /build /dist /node_modules diff --git a/javascript/CMakeLists.txt b/javascript/CMakeLists.txt index 01177fcc..afb54bb5 100644 --- a/javascript/CMakeLists.txt +++ b/javascript/CMakeLists.txt @@ -49,7 +49,7 @@ link_libraries(embind) add_library(yogaObjLib OBJECT ${SOURCES}) -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/dist/build) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/binaries) add_executable(asmjs-sync $) target_link_options(asmjs-sync PUBLIC diff --git a/javascript/README.md b/javascript/README.md index ceeb50ac..87b07a2e 100644 --- a/javascript/README.md +++ b/javascript/README.md @@ -44,7 +44,7 @@ For better performance and smaller packages, WebAssembly is preferred to asm.js A specific entrypoint may be specified on platforms which do not understand export conditions. ```ts -import {loadYoga} from 'yoga-layout/dist/entrypoint/wasm-async'; +import {loadYoga} from 'yoga-layout/wasm-async'; ``` diff --git a/javascript/jest.setup.ts b/javascript/jest.setup.ts index 13639817..7ec11a77 100644 --- a/javascript/jest.setup.ts +++ b/javascript/jest.setup.ts @@ -9,13 +9,13 @@ module.exports = async () => { if (process.env['SYNC'] === '1' && process.env['WASM'] === '1') { - globalThis.Yoga = require('./dist/entrypoint/wasm-sync'); + globalThis.Yoga = require('yoga-layout/wasm-sync').default; } else if (process.env['SYNC'] === '1') { - globalThis.Yoga = require('./dist/entrypoint/asmjs-sync'); + globalThis.Yoga = require('yoga-layout/asmjs-sync').default; } else if (process.env['WASM'] === '1') { - globalThis.Yoga = await require('./dist/entrypoint/wasm-async').loadYoga(); + globalThis.Yoga = await require('yoga-layout/wasm-async').loadYoga(); } else { - globalThis.Yoga = await require('./dist/entrypoint/asmjs-async').loadYoga(); + globalThis.Yoga = await require('yoga-layout/asmjs-async').loadYoga(); } }; diff --git a/javascript/just.config.ts b/javascript/just.config.ts index dcc7776e..11d45988 100644 --- a/javascript/just.config.ts +++ b/javascript/just.config.ts @@ -21,6 +21,8 @@ import { tscTask, } from 'just-scripts'; +import {readFile, writeFile} from 'fs/promises'; + import glob from 'glob'; import path from 'path'; import which from 'which'; @@ -84,15 +86,38 @@ task( ), ); +task('prepack-package-json', async () => { + const packageJsonPath = path.join(__dirname, 'package.json'); + const packageJsonContents = await readFile(packageJsonPath); + const packageJson = JSON.parse(packageJsonContents.toString('utf-8')); + + recursiveReplace(packageJson, /(.\/src\/.*)\.ts/, '$1.js'); + await writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2)); +}); + task( - 'prepublish', - parallel( - 'build', - tscTask({emitDeclarationOnly: true}), + 'prepack', + series( + parallel('build', tscTask({emitDeclarationOnly: true})), babelTransformTask({dir: 'src'}), + 'prepack-package-json', ), ); +function recursiveReplace( + obj: Record, + pattern: RegExp, + replacement: string, +) { + for (const [key, value] of Object.entries(obj)) { + if (typeof value === 'string') { + obj[key] = value.replace(pattern, replacement); + } else if (typeof value === 'object' && value != null) { + recursiveReplace(value as Record, pattern, replacement); + } + } +} + function babelTransformTask(opts: {dir: string}) { return () => { const args = [ diff --git a/javascript/package.json b/javascript/package.json index 683ec3b3..b1f9d913 100644 --- a/javascript/package.json +++ b/javascript/package.json @@ -7,22 +7,24 @@ "type": "git", "url": "git@github.com:facebook/yoga.git" }, - "main": "./src/index.js", - "types": "./src/index.d.ts", "exports": { ".": { - "browser": "./src/entrypoint/wasm-async.js", - "node": "./src/entrypoint/wasm-async.js", - "default": "./src/entrypoint/asmjs-async.js" + "browser": "./src/entrypoint/wasm-async.ts", + "node": "./src/entrypoint/wasm-async.ts", + "default": "./src/entrypoint/asmjs-async.ts" }, "./sync": { - "browser": "./src/entrypoint/asmjs-sync.js", - "node": "./src/entrypoint/wasm-sync.js", - "default": "./src/entrypoint/asmjs-sync.js" - } + "browser": "./src/entrypoint/asmjs-sync.ts", + "node": "./src/entrypoint/wasm-sync.ts", + "default": "./src/entrypoint/asmjs-sync.ts" + }, + "./asmjs-async": "./src/entrypoint/asmjs-async.ts", + "./asmjs-sync": "./src/entrypoint/asmjs-sync.ts", + "./wasm-async": "./src/entrypoint/wasm-async.ts", + "./wasm-sync": "./src/entrypoint/wasm-sync.ts" }, "files": [ - "dist/**", + "binaries/**", "src/**" ], "scripts": { @@ -31,7 +33,7 @@ "clean": "just clean", "lint": "just lint", "lint:fix": "just lint --fix", - "prepublish": "just prepublish", + "prepack": "just prepack", "test": "just test", "test:asmjs-async": "just test:asmjs-async", "test:asmjs-sync": "just test:asmjs-sync", diff --git a/javascript/src/entrypoint/_entryAsync.js b/javascript/src/entrypoint/_entryAsync.js deleted file mode 100644 index 7d46c388..00000000 --- a/javascript/src/entrypoint/_entryAsync.js +++ /dev/null @@ -1,15 +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 - */ - -const wrapAsm = require('../wrapAsm'); - -module.exports = loadAsm => ({ - loadYoga: () => loadAsm().then(wrapAsm), - ...require('../generated/YGEnums'), -}); diff --git a/javascript/src/entrypoint/_entrySync.js b/javascript/src/entrypoint/_entrySync.js deleted file mode 100644 index 9495d98c..00000000 --- a/javascript/src/entrypoint/_entrySync.js +++ /dev/null @@ -1,11 +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 - */ - -const wrapAsm = require('../wrapAsm'); -module.exports = asm => wrapAsm(asm()); diff --git a/javascript/src/entrypoint/asmjs-async.js b/javascript/src/entrypoint/asmjs-async.js deleted file mode 100644 index eb1b52d7..00000000 --- a/javascript/src/entrypoint/asmjs-async.js +++ /dev/null @@ -1,11 +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 - */ - -const asm = require('../build/asmjs-async'); -module.exports = require('./_entryAsync')(asm); diff --git a/javascript/src/entrypoint/asmjs-async.ts b/javascript/src/entrypoint/asmjs-async.ts new file mode 100644 index 00000000..5ac7c71a --- /dev/null +++ b/javascript/src/entrypoint/asmjs-async.ts @@ -0,0 +1,26 @@ +/** + * 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 wrapAssembly from '../wrapAssembly'; +import type {Yoga} from '../wrapAssembly'; + +export * from '../generated/YGEnums'; +export type { + Config, + DirtiedFunction, + MeasureFunction, + Node, + Yoga, +} from '../wrapAssembly'; + +const loadAssembly = require('../../binaries/asmjs-async'); + +export async function loadYoga(): Promise { + return wrapAssembly(await loadAssembly()); +} diff --git a/javascript/src/entrypoint/asmjs-sync.js b/javascript/src/entrypoint/asmjs-sync.js deleted file mode 100644 index 69197714..00000000 --- a/javascript/src/entrypoint/asmjs-sync.js +++ /dev/null @@ -1,11 +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 - */ - -const asm = require('../build/asmjs-sync'); -module.exports = require('./_entrySync')(asm); diff --git a/javascript/src/entrypoint/asmjs-sync.ts b/javascript/src/entrypoint/asmjs-sync.ts new file mode 100644 index 00000000..710dbdbe --- /dev/null +++ b/javascript/src/entrypoint/asmjs-sync.ts @@ -0,0 +1,23 @@ +/** + * 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 wrapAssembly from '../wrapAssembly'; + +export * from '../generated/YGEnums'; +export type { + Config, + DirtiedFunction, + MeasureFunction, + Node, + Yoga, +} from '../wrapAssembly'; + +const loadAssembly = require('../../binaries/asmjs-sync'); +const Yoga = wrapAssembly(loadAssembly()); +export default Yoga; diff --git a/javascript/src/entrypoint/wasm-async.js b/javascript/src/entrypoint/wasm-async.js deleted file mode 100644 index ad5be421..00000000 --- a/javascript/src/entrypoint/wasm-async.js +++ /dev/null @@ -1,11 +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 - */ - -const asm = require('../build/wasm-async'); -module.exports = require('./_entryAsync')(asm); diff --git a/javascript/src/entrypoint/wasm-async.ts b/javascript/src/entrypoint/wasm-async.ts new file mode 100644 index 00000000..752f759d --- /dev/null +++ b/javascript/src/entrypoint/wasm-async.ts @@ -0,0 +1,26 @@ +/** + * 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 wrapAssembly from '../wrapAssembly'; +import type {Yoga} from '../wrapAssembly'; + +export * from '../generated/YGEnums'; +export type { + Config, + DirtiedFunction, + MeasureFunction, + Node, + Yoga, +} from '../wrapAssembly'; + +const loadAssembly = require('../../binaries/wasm-async'); + +export async function loadYoga(): Promise { + return wrapAssembly(await loadAssembly()); +} diff --git a/javascript/src/entrypoint/wasm-sync.js b/javascript/src/entrypoint/wasm-sync.js deleted file mode 100644 index 88983508..00000000 --- a/javascript/src/entrypoint/wasm-sync.js +++ /dev/null @@ -1,11 +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 - */ - -const asm = require('../build/wasm-sync'); -module.exports = require('./_entrySync')(asm); diff --git a/javascript/src/entrypoint/wasm-sync.ts b/javascript/src/entrypoint/wasm-sync.ts new file mode 100644 index 00000000..ff9bf702 --- /dev/null +++ b/javascript/src/entrypoint/wasm-sync.ts @@ -0,0 +1,23 @@ +/** + * 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 wrapAssembly from '../wrapAssembly'; + +export * from '../generated/YGEnums'; +export type { + Config, + DirtiedFunction, + MeasureFunction, + Node, + Yoga, +} from '../wrapAssembly'; + +const loadAssembly = require('../../binaries/wasm-sync'); +const Yoga = wrapAssembly(loadAssembly()); +export default Yoga; diff --git a/javascript/src/index.d.ts b/javascript/src/index.d.ts deleted file mode 100644 index fb2830e4..00000000 --- a/javascript/src/index.d.ts +++ /dev/null @@ -1,15 +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 type {Yoga} from './wrapAsm'; - -export * from './generated/YGEnums'; -export * from './wrapAsm'; - -export function loadYoga(): Promise; diff --git a/javascript/src/index.js b/javascript/src/index.js deleted file mode 100644 index 06a348c4..00000000 --- a/javascript/src/index.js +++ /dev/null @@ -1,11 +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 - */ - -// Fallback for when the export map is not followed -module.exports = require('./entrypoint/asmjs-async'); diff --git a/javascript/src/sync.d.ts b/javascript/src/sync.d.ts deleted file mode 100644 index 27bd8ecc..00000000 --- a/javascript/src/sync.d.ts +++ /dev/null @@ -1,16 +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 type {Yoga} from './wrapAsm'; - -export * from './generated/YGEnums'; -export * from './wrapAsm'; - -declare const yoga: Yoga; -export default yoga; diff --git a/javascript/src/sync.js b/javascript/src/sync.js deleted file mode 100644 index 6ac610ef..00000000 --- a/javascript/src/sync.js +++ /dev/null @@ -1,11 +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 - */ - -// Fallback for when the export map is not followed -module.exports = require('./entrypoint/asmjs-sync'); diff --git a/javascript/src/wrapAsm.d.ts b/javascript/src/wrapAssembly.d.ts similarity index 99% rename from javascript/src/wrapAsm.d.ts rename to javascript/src/wrapAssembly.d.ts index d3dc069d..0b0b38b2 100644 --- a/javascript/src/wrapAsm.d.ts +++ b/javascript/src/wrapAssembly.d.ts @@ -187,5 +187,5 @@ export type Yoga = { }; } & typeof YGEnums; -declare const wrapAsm: () => Yoga; +declare const wrapAsm: (assembly: unknown) => Yoga; export default wrapAsm; diff --git a/javascript/src/wrapAsm.js b/javascript/src/wrapAssembly.js similarity index 100% rename from javascript/src/wrapAsm.js rename to javascript/src/wrapAssembly.js diff --git a/javascript/tests/bin/run-bench.ts b/javascript/tests/bin/run-bench.ts index 836f7f0b..d5c4d088 100644 --- a/javascript/tests/bin/run-bench.ts +++ b/javascript/tests/bin/run-bench.ts @@ -10,6 +10,9 @@ import path from 'path'; +import YogaAsmjs from 'yoga-layout/asmjs-sync'; +import YogaWasm from 'yoga-layout/wasm-sync'; + const WARMUP_ITERATIONS = 3; const BENCHMARK_ITERATIONS = 10; @@ -18,9 +21,7 @@ const testFiles = process.argv.slice(2); const testResults = new Map>(); for (const type of ['asmjs', 'wasm']) { - globalThis.Yoga = require(type === 'asmjs' - ? '../../dist/entrypoint/asmjs-sync' - : '../../dist/entrypoint/wasm-sync'); + globalThis.Yoga = type === 'asmjs' ? YogaAsmjs : YogaWasm; for (const file of testFiles) { globalThis.YGBENCHMARK = (name: string, fn: () => void) => { diff --git a/javascript/tsconfig.json b/javascript/tsconfig.json index 2568d1e1..ba6074ad 100644 --- a/javascript/tsconfig.json +++ b/javascript/tsconfig.json @@ -6,8 +6,11 @@ "declaration": true, "esModuleInterop": true, "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, + // TODO: moduleResolution: "nodenext" is buggy with this if the absolute + // path contains any capital letters + "forceConsistentCasingInFileNames": false, "baseUrl": ".", + "moduleResolution": "nodenext", "paths": { "yoga-layout": ["src"] }