Consolidate JavaScript Flavors #1433
88
.eslintrc.cjs
Normal file
88
.eslintrc.cjs
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
/**
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
root: true,
|
||||||
|
ignorePatterns: [
|
||||||
|
'/website',
|
||||||
|
'**/binaries/**',
|
||||||
|
'**/build/**',
|
||||||
|
'**/generated/**',
|
||||||
|
],
|
||||||
|
overrides: [
|
||||||
|
// Catch-all
|
||||||
|
{
|
||||||
|
files: ['**/*.?(m|c){j,t}s?(x)'],
|
||||||
|
extends: ['eslint:recommended', 'plugin:prettier/recommended'],
|
||||||
|
plugins: ['prettier'],
|
||||||
|
rules: {
|
||||||
|
'no-unused-vars': ['error', {argsIgnorePattern: '^_'}],
|
||||||
|
'no-var': 'error',
|
||||||
|
'prefer-arrow-callback': 'error',
|
||||||
|
'prefer-const': 'error',
|
||||||
|
'prefer-object-spread': 'error',
|
||||||
|
'prefer-spread': 'error',
|
||||||
|
'require-await': 'error',
|
||||||
|
},
|
||||||
|
env: {
|
||||||
|
es2020: true,
|
||||||
|
},
|
||||||
|
parserOptions: {
|
||||||
|
ecmaVersion: 'latest',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// ES Modules
|
||||||
|
{
|
||||||
|
files: ['**/*.?(m){j,t}s?(x)'],
|
||||||
|
parserOptions: {
|
||||||
|
sourceType: 'module',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// CommonJS Modules
|
||||||
|
{
|
||||||
|
files: ['**/*.c{j,t}s?(x)'],
|
||||||
|
env: {
|
||||||
|
commonjs: true,
|
||||||
|
},
|
||||||
|
parserOptions: {
|
||||||
|
sourceType: 'commonjs',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// TypeScript
|
||||||
|
{
|
||||||
|
files: ['**/*.?(m|c)ts?(x)'],
|
||||||
|
extends: ['plugin:@typescript-eslint/recommended'],
|
||||||
|
parser: '@typescript-eslint/parser',
|
||||||
|
parserOptions: {
|
||||||
|
project: true,
|
||||||
|
},
|
||||||
|
plugins: ['@typescript-eslint'],
|
||||||
|
rules: {
|
||||||
|
'@typescript-eslint/ban-ts-comment': 'off',
|
||||||
|
'@typescript-eslint/no-unused-vars': [
|
||||||
|
'error',
|
||||||
|
{argsIgnorePattern: '^_'},
|
||||||
|
],
|
||||||
|
'@typescript-eslint/no-var-requires': 'off',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// Node
|
||||||
|
{
|
||||||
|
files: ['**/.*rc.(c){j,t}s', '**/*.config.?(c){j,t}s'],
|
||||||
|
env: {
|
||||||
|
node: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// Jest
|
||||||
|
{
|
||||||
|
files: ['**/tests/**'],
|
||||||
|
extends: ['plugin:jest/recommended'],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
76
.eslintrc.js
76
.eslintrc.js
@@ -1,76 +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
|
|
||||||
*/
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
root: true,
|
|
||||||
ignorePatterns: [
|
|
||||||
'/website',
|
|
||||||
'**/binaries/**',
|
|
||||||
'**/build/**',
|
|
||||||
'**/generated/**',
|
|
||||||
],
|
|
||||||
extends: ['eslint:recommended', 'plugin:prettier/recommended'],
|
|
||||||
plugins: ['prettier'],
|
|
||||||
rules: {
|
|
||||||
'no-unused-vars': ['error', {argsIgnorePattern: '^_'}],
|
|
||||||
'no-var': 'error',
|
|
||||||
'prefer-arrow-callback': 'error',
|
|
||||||
'prefer-const': 'error',
|
|
||||||
'prefer-object-spread': 'error',
|
|
||||||
'prefer-spread': 'error',
|
|
||||||
'require-await': 'error',
|
|
||||||
},
|
|
||||||
env: {
|
|
||||||
commonjs: true,
|
|
||||||
es2018: true,
|
|
||||||
},
|
|
||||||
parserOptions: {
|
|
||||||
sourceType: 'module',
|
|
||||||
ecmaVersion: 'latest',
|
|
||||||
},
|
|
||||||
overrides: [
|
|
||||||
{
|
|
||||||
files: ['**/*.ts', '**/*.tsx'],
|
|
||||||
extends: ['plugin:@typescript-eslint/recommended'],
|
|
||||||
parser: '@typescript-eslint/parser',
|
|
||||||
parserOptions: {
|
|
||||||
project: true,
|
|
||||||
},
|
|
||||||
plugins: ['@typescript-eslint'],
|
|
||||||
rules: {
|
|
||||||
'@typescript-eslint/ban-ts-comment': 'off',
|
|
||||||
'@typescript-eslint/no-unused-vars': [
|
|
||||||
'error',
|
|
||||||
{argsIgnorePattern: '^_'},
|
|
||||||
],
|
|
||||||
'@typescript-eslint/no-var-requires': 'off',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
files: ['**/.eslintrc.js', '**/just.config.js'],
|
|
||||||
env: {
|
|
||||||
node: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
files: ['jest.*', '**/tests/**'],
|
|
||||||
env: {
|
|
||||||
node: true,
|
|
||||||
},
|
|
||||||
extends: ['plugin:jest/recommended'],
|
|
||||||
globals: {
|
|
||||||
getMeasureCounter: 'writable',
|
|
||||||
getMeasureCounterMax: 'writable',
|
|
||||||
getMeasureCounterMin: 'writable',
|
|
||||||
Yoga: 'writable',
|
|
||||||
YGBENCHMARK: 'writable',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
@@ -23,7 +23,7 @@ JavascriptEmitter.prototype = Object.create(Emitter.prototype, {
|
|||||||
|
|
||||||
emitPrologue: {
|
emitPrologue: {
|
||||||
value: function () {
|
value: function () {
|
||||||
this.push('import {Yoga} from "../tools/globals";');
|
this.push("import Yoga from 'yoga-layout';");
|
||||||
this.push('import {');
|
this.push('import {');
|
||||||
this.pushIndent();
|
this.pushIndent();
|
||||||
this.push('Align,');
|
this.push('Align,');
|
||||||
|
@@ -31,9 +31,9 @@ add_compile_options(${COMPILE_OPTIONS})
|
|||||||
|
|
||||||
add_link_options(
|
add_link_options(
|
||||||
${COMPILE_OPTIONS}
|
${COMPILE_OPTIONS}
|
||||||
--closure 1
|
"SHELL:--closure 1"
|
||||||
--memory-init-file 0
|
"SHELL:--memory-init-file 0"
|
||||||
--no-entry
|
"SHELL:--no-entry"
|
||||||
"SHELL:-s ALLOW_MEMORY_GROWTH=1"
|
"SHELL:-s ALLOW_MEMORY_GROWTH=1"
|
||||||
"SHELL:-s ASSERTIONS=0"
|
"SHELL:-s ASSERTIONS=0"
|
||||||
"SHELL:-s DYNAMIC_EXECUTION=0"
|
"SHELL:-s DYNAMIC_EXECUTION=0"
|
||||||
@@ -42,8 +42,9 @@ add_link_options(
|
|||||||
"SHELL:-s FILESYSTEM=0"
|
"SHELL:-s FILESYSTEM=0"
|
||||||
"SHELL:-s MALLOC='emmalloc'"
|
"SHELL:-s MALLOC='emmalloc'"
|
||||||
"SHELL:-s MODULARIZE=1"
|
"SHELL:-s MODULARIZE=1"
|
||||||
"SHELL:-s TEXTDECODER=0"
|
"SHELL:-s EXPORT_ES6=1"
|
||||||
"SHELL:-s SINGLE_FILE=1")
|
"SHELL:-s WASM=1"
|
||||||
|
"SHELL:-s TEXTDECODER=0")
|
||||||
|
|
||||||
link_libraries(embind)
|
link_libraries(embind)
|
||||||
|
|
||||||
@@ -51,62 +52,9 @@ add_library(yogaObjLib OBJECT ${SOURCES})
|
|||||||
|
|
||||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/binaries)
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/binaries)
|
||||||
|
|
||||||
add_executable(asmjs-sync-node $<TARGET_OBJECTS:yogaObjLib>)
|
add_executable(web $<TARGET_OBJECTS:yogaObjLib>)
|
||||||
target_link_options(asmjs-sync-node PUBLIC
|
target_link_options(web PRIVATE
|
||||||
"SHELL:-s ENVIRONMENT='node'"
|
# SINGLE_FILE=1 combined with ENVIRONMENT='web' creates code that works on
|
||||||
"SHELL:-s WASM=0"
|
# both bundlders and Node.
|
||||||
"SHELL:-s WASM_ASYNC_COMPILATION=0")
|
"SHELL:-s SINGLE_FILE=1"
|
||||||
|
"SHELL:-s ENVIRONMENT='web'")
|
||||||
add_executable(asmjs-async-node $<TARGET_OBJECTS:yogaObjLib>)
|
|
||||||
target_link_options(asmjs-async-node PUBLIC
|
|
||||||
"SHELL:-s ENVIRONMENT='node'"
|
|
||||||
"SHELL:-s WASM=0"
|
|
||||||
"SHELL:-s WASM_ASYNC_COMPILATION=1")
|
|
||||||
|
|
||||||
add_executable(asmjs-sync-web $<TARGET_OBJECTS:yogaObjLib>)
|
|
||||||
target_link_options(asmjs-sync-web PUBLIC
|
|
||||||
"SHELL:-s ENVIRONMENT='web'"
|
|
||||||
"SHELL:-s WASM=0"
|
|
||||||
"SHELL:-s WASM_ASYNC_COMPILATION=0")
|
|
||||||
|
|
||||||
add_executable(asmjs-async-web $<TARGET_OBJECTS:yogaObjLib>)
|
|
||||||
target_link_options(asmjs-async-web PUBLIC
|
|
||||||
"SHELL:-s ENVIRONMENT='web'"
|
|
||||||
"SHELL:-s WASM=0"
|
|
||||||
"SHELL:-s WASM_ASYNC_COMPILATION=1")
|
|
||||||
|
|
||||||
add_executable(asmjs-sync $<TARGET_OBJECTS:yogaObjLib>)
|
|
||||||
target_link_options(asmjs-sync PUBLIC
|
|
||||||
"SHELL:-s ENVIRONMENT='web,node'"
|
|
||||||
"SHELL:-s WASM=0"
|
|
||||||
"SHELL:-s WASM_ASYNC_COMPILATION=0")
|
|
||||||
|
|
||||||
add_executable(asmjs-async $<TARGET_OBJECTS:yogaObjLib>)
|
|
||||||
target_link_options(asmjs-async PUBLIC
|
|
||||||
"SHELL:-s ENVIRONMENT='web,node'"
|
|
||||||
"SHELL:-s WASM=0"
|
|
||||||
"SHELL:-s WASM_ASYNC_COMPILATION=1")
|
|
||||||
|
|
||||||
add_executable(wasm-sync-node $<TARGET_OBJECTS:yogaObjLib>)
|
|
||||||
target_link_options(wasm-sync-node PUBLIC
|
|
||||||
"SHELL:-s ENVIRONMENT='node'"
|
|
||||||
"SHELL:-s WASM=1"
|
|
||||||
"SHELL:-s WASM_ASYNC_COMPILATION=0")
|
|
||||||
|
|
||||||
add_executable(wasm-async-node $<TARGET_OBJECTS:yogaObjLib>)
|
|
||||||
target_link_options(wasm-async-node PUBLIC
|
|
||||||
"SHELL:-s ENVIRONMENT='node'"
|
|
||||||
"SHELL:-s WASM=1"
|
|
||||||
"SHELL:-s WASM_ASYNC_COMPILATION=1")
|
|
||||||
|
|
||||||
add_executable(wasm-sync-web $<TARGET_OBJECTS:yogaObjLib>)
|
|
||||||
target_link_options(wasm-sync-web PUBLIC
|
|
||||||
"SHELL:-s ENVIRONMENT='web'"
|
|
||||||
"SHELL:-s WASM=1"
|
|
||||||
"SHELL:-s WASM_ASYNC_COMPILATION=0")
|
|
||||||
|
|
||||||
add_executable(wasm-async-web $<TARGET_OBJECTS:yogaObjLib>)
|
|
||||||
target_link_options(wasm-async-web PUBLIC
|
|
||||||
"SHELL:-s ENVIRONMENT='web'"
|
|
||||||
"SHELL:-s WASM=1"
|
|
||||||
"SHELL:-s WASM_ASYNC_COMPILATION=1")
|
|
||||||
|
@@ -1,24 +1,11 @@
|
|||||||
# yoga-layout
|
# yoga-layout
|
||||||
|
|
||||||
This package provides prebuilt JavaScript bindings for the Yoga layout engine. Both WebAssembly and asm.js variants are packaged, with the optimal loaded based on platform.
|
This package provides prebuilt WebAssembly bindings for the Yoga layout engine.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
The default entrypoint provides an asynchronous loader function to return a Yoga instance.
|
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import {loadYoga, Align} from 'yoga-layout';
|
import {Yoga, Align} from 'yoga-layout';
|
||||||
|
|
||||||
const Yoga = await loadYoga();
|
|
||||||
|
|
||||||
const node = Yoga.Node.create();
|
|
||||||
node.setAlignContent(Align.Center);
|
|
||||||
```
|
|
||||||
|
|
||||||
An alternative synchronous API is provided for compatibility, but requires using asm.js in browsers instead of WebAssembly, leading to worse performance and larger assets.
|
|
||||||
|
|
||||||
```ts
|
|
||||||
import Yoga, {Align} from 'yoga-layout/sync';
|
|
||||||
|
|
||||||
const node = Yoga.Node.create();
|
const node = Yoga.Node.create();
|
||||||
node.setAlignContent(Align.Center);
|
node.setAlignContent(Align.Center);
|
||||||
@@ -37,20 +24,14 @@ node.freeRecursive();
|
|||||||
node.free();
|
node.free();
|
||||||
```
|
```
|
||||||
|
|
||||||
## Selecting WebAssembly or asm.js
|
|
||||||
|
|
||||||
For better performance and smaller packages, WebAssembly is preferred to asm.js where available. `yoga-layout` tries to provide the right default using [export maps](https://webpack.js.org/guides/package-exports/#conditional-syntax) so that platforms which can take advantage of WebAssembly use it by default.
|
|
||||||
|
|
||||||
Different entrypoints are exposed to choose a flavor explicitly.
|
|
||||||
|
|
||||||
```ts
|
|
||||||
import {loadYoga} from 'yoga-layout/wasm-async';
|
|
||||||
```
|
|
||||||
|
|
||||||
## Using TypeScript
|
## Using TypeScript
|
||||||
|
|
||||||
This package provides out-of-the-box TypeScript typings so long as `tsc` is configured to support ESM resolution. It is recommended to set `moduleResolution: 'bundler'` or `moduleResolution: node16` in your `tsconfig.json` according to your environment.
|
This package provides out-of-the-box TypeScript typings so long as `tsc` is configured to support ESM resolution. It is recommended to set `moduleResolution: 'bundler'` or `moduleResolution: node16` in your `tsconfig.json` according to your environment.
|
||||||
|
|
||||||
|
## ES Modules
|
||||||
|
|
||||||
|
`yoga-layout` is only provided as an ES Module, relying on top-level await. This allows providing a synchronous API, while still allowing async WebAssembly compilation in browsers, and will allow eventual usage of ESM/WASM interop.
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
### Requirements
|
### Requirements
|
||||||
|
30
javascript/babel.config.cjs
Normal file
30
javascript/babel.config.cjs
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
/**
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports = api => ({
|
||||||
|
presets: [
|
||||||
|
[
|
||||||
|
'@babel/preset-env',
|
||||||
|
{
|
||||||
|
targets: [
|
||||||
|
'maintained node versions',
|
||||||
|
'> 0.5%, last 2 versions, Firefox ESR, not dead',
|
||||||
|
],
|
||||||
|
// Do not transform to another module system
|
||||||
|
modules: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'@babel/preset-typescript',
|
||||||
|
{
|
||||||
|
rewriteImportExtensions: api.env('dist'),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
],
|
||||||
|
});
|
@@ -7,9 +7,8 @@
|
|||||||
* @format
|
* @format
|
||||||
*/
|
*/
|
||||||
|
|
||||||
module.exports = {
|
export default {
|
||||||
presets: [
|
setupFiles: ['./jest.setup.js'],
|
||||||
['@babel/preset-env', {targets: 'defaults'}],
|
testRegex: '/tests/.*\\.test\\.ts$',
|
||||||
'@babel/preset-typescript',
|
extensionsToTreatAsEsm: ['.ts'],
|
||||||
],
|
|
||||||
};
|
};
|
@@ -1,27 +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 {Config} from 'jest';
|
|
||||||
|
|
||||||
const config: Config = {
|
|
||||||
setupFiles: ['./jest.setup.ts'],
|
|
||||||
testRegex: '/tests/.*\\.test\\.[jt]s$',
|
|
||||||
moduleNameMapper: {
|
|
||||||
'yoga-layout':
|
|
||||||
process.env['SYNC'] === '1' && process.env['WASM'] === '1'
|
|
||||||
? 'yoga-layout/wasm-sync'
|
|
||||||
: process.env['SYNC'] === '1'
|
|
||||||
? 'yoga-layout/asmjs-sync'
|
|
||||||
: process.env['WASM'] === '1'
|
|
||||||
? 'yoga-layout/wasm-async'
|
|
||||||
: 'yoga-layout/asmjs-async',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export default config;
|
|
@@ -7,11 +7,6 @@
|
|||||||
* @format
|
* @format
|
||||||
*/
|
*/
|
||||||
|
|
||||||
module.exports = async () => {
|
|
||||||
const {loadYoga, default: Yoga} = require('yoga-layout');
|
|
||||||
globalThis.Yoga = Yoga ?? (await loadYoga());
|
|
||||||
};
|
|
||||||
|
|
||||||
Object.defineProperty(globalThis, 'YGBENCHMARK', {
|
Object.defineProperty(globalThis, 'YGBENCHMARK', {
|
||||||
get: () => globalThis.test,
|
get: () => globalThis.test,
|
||||||
});
|
});
|
@@ -7,7 +7,7 @@
|
|||||||
* @format
|
* @format
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {
|
const {
|
||||||
argv,
|
argv,
|
||||||
cleanTask,
|
cleanTask,
|
||||||
logger,
|
logger,
|
||||||
@@ -18,13 +18,13 @@ import {
|
|||||||
spawn,
|
spawn,
|
||||||
task,
|
task,
|
||||||
tscTask,
|
tscTask,
|
||||||
} from 'just-scripts';
|
} = require('just-scripts');
|
||||||
|
|
||||||
import {readFile, writeFile} from 'fs/promises';
|
const {readFile, writeFile} = require('fs/promises');
|
||||||
|
|
||||||
import glob from 'glob';
|
const glob = require('glob');
|
||||||
import path from 'path';
|
const path = require('path');
|
||||||
import which from 'which';
|
const which = require('which');
|
||||||
|
|
||||||
const node = process.execPath;
|
const node = process.execPath;
|
||||||
|
|
||||||
@@ -32,11 +32,15 @@ option('fix');
|
|||||||
|
|
||||||
task('clean', cleanTask({paths: ['build', 'dist']}));
|
task('clean', cleanTask({paths: ['build', 'dist']}));
|
||||||
|
|
||||||
function defineFlavor(flavor: string, env: NodeJS.ProcessEnv) {
|
function defineFlavor(flavor, env) {
|
||||||
task(`cmake-build:${flavor}`, cmakeBuildTask({targets: [flavor]}));
|
task(`cmake-build:${flavor}`, cmakeBuildTask({targets: [flavor]}));
|
||||||
task(
|
task(
|
||||||
`jest:${flavor}`,
|
`jest:${flavor}`,
|
||||||
jestTask({config: path.join(__dirname, 'jest.config.ts'), env}),
|
jestTask({
|
||||||
|
config: path.join(__dirname, 'jest.config.js'),
|
||||||
|
nodeArgs: ['--experimental-vm-modules'],
|
||||||
|
env,
|
||||||
|
}),
|
||||||
);
|
);
|
||||||
task(
|
task(
|
||||||
`test:${flavor}`,
|
`test:${flavor}`,
|
||||||
@@ -44,33 +48,17 @@ function defineFlavor(flavor: string, env: NodeJS.ProcessEnv) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
defineFlavor('asmjs-async-node', {WASM: '0', SYNC: '0'});
|
defineFlavor('web');
|
||||||
defineFlavor('asmjs-sync-node', {WASM: '0', SYNC: '1'});
|
|
||||||
defineFlavor('asmjs-async-web', {WASM: '0', SYNC: '0'});
|
|
||||||
defineFlavor('asmjs-sync-web', {WASM: '0', SYNC: '1'});
|
|
||||||
defineFlavor('wasm-async-node', {WASM: '1', SYNC: '0'});
|
|
||||||
defineFlavor('wasm-sync-node', {WASM: '1', SYNC: '1'});
|
|
||||||
defineFlavor('wasm-async-web', {WASM: '1', SYNC: '0'});
|
|
||||||
defineFlavor('wasm-sync-web', {WASM: '1', SYNC: '1'});
|
|
||||||
|
|
||||||
task('build', series(emcmakeGenerateTask(), cmakeBuildTask()));
|
task('build', series(emcmakeGenerateTask(), cmakeBuildTask()));
|
||||||
|
|
||||||
task(
|
task('test', series(emcmakeGenerateTask(), 'cmake-build:web', 'jest:web'));
|
||||||
'test',
|
|
||||||
series(
|
|
||||||
emcmakeGenerateTask(),
|
|
||||||
series('cmake-build:asmjs-async-node', 'jest:asmjs-async-node'),
|
|
||||||
series('cmake-build:asmjs-sync-node', 'jest:asmjs-sync-node'),
|
|
||||||
series('cmake-build:wasm-async-node', 'jest:wasm-async-node'),
|
|
||||||
series('cmake-build:wasm-sync-node', 'jest:wasm-sync-node'),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
task(
|
task(
|
||||||
'benchmark',
|
'benchmark',
|
||||||
series(
|
series(
|
||||||
emcmakeGenerateTask(),
|
emcmakeGenerateTask(),
|
||||||
cmakeBuildTask({targets: ['asmjs-sync-node', 'wasm-sync-node']}),
|
cmakeBuildTask({targets: ['web']}),
|
||||||
runBenchTask(),
|
runBenchTask(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -95,21 +83,17 @@ task(
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
function recursiveReplace(
|
function recursiveReplace(obj, pattern, replacement) {
|
||||||
obj: Record<string, unknown>,
|
|
||||||
pattern: RegExp,
|
|
||||||
replacement: string,
|
|
||||||
) {
|
|
||||||
for (const [key, value] of Object.entries(obj)) {
|
for (const [key, value] of Object.entries(obj)) {
|
||||||
if (typeof value === 'string') {
|
if (typeof value === 'string') {
|
||||||
obj[key] = value.replace(pattern, replacement);
|
obj[key] = value.replace(pattern, replacement);
|
||||||
} else if (typeof value === 'object' && value != null) {
|
} else if (typeof value === 'object' && value != null) {
|
||||||
recursiveReplace(value as Record<string, unknown>, pattern, replacement);
|
recursiveReplace(value, pattern, replacement);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function babelTransformTask(opts: {dir: string}) {
|
function babelTransformTask(opts) {
|
||||||
return () => {
|
return () => {
|
||||||
const args = [
|
const args = [
|
||||||
opts.dir,
|
opts.dir,
|
||||||
@@ -117,12 +101,16 @@ function babelTransformTask(opts: {dir: string}) {
|
|||||||
'--out-dir',
|
'--out-dir',
|
||||||
opts.dir,
|
opts.dir,
|
||||||
'--extensions',
|
'--extensions',
|
||||||
'.js,.ts',
|
'.js,.cjs,.mjs,.ts,.cts,.mts',
|
||||||
];
|
];
|
||||||
logger.info(`Transforming "${path.resolve(opts.dir)}"`);
|
logger.info(`Transforming "${path.resolve(opts.dir)}"`);
|
||||||
|
|
||||||
return spawn(node, [require.resolve('@babel/cli/bin/babel'), ...args], {
|
return spawn(node, [require.resolve('@babel/cli/bin/babel'), ...args], {
|
||||||
cwd: __dirname,
|
cwd: __dirname,
|
||||||
|
env: {
|
||||||
|
// Trigger distribution-specific Babel transforms
|
||||||
|
NODE_ENV: 'dist',
|
||||||
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -132,23 +120,15 @@ function runBenchTask() {
|
|||||||
const files = glob.sync('./tests/Benchmarks/**/*');
|
const files = glob.sync('./tests/Benchmarks/**/*');
|
||||||
|
|
||||||
const args = [
|
const args = [
|
||||||
'--extensions',
|
'--loader=babel-register-esm',
|
||||||
'.js,.ts',
|
|
||||||
'--config-file',
|
|
||||||
path.join(__dirname, '.babelrc.js'),
|
|
||||||
'--',
|
|
||||||
'./tests/bin/run-bench.ts',
|
'./tests/bin/run-bench.ts',
|
||||||
...files,
|
...files,
|
||||||
];
|
];
|
||||||
logger.info(['babel-node', ...args].join(' '));
|
logger.info(['node', ...args].join(' '));
|
||||||
|
|
||||||
return spawn(
|
return spawn(node, args, {
|
||||||
node,
|
stdio: 'inherit',
|
||||||
[require.resolve('@babel/node/bin/babel-node'), ...args],
|
});
|
||||||
{
|
|
||||||
stdio: 'inherit',
|
|
||||||
},
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,7 +150,7 @@ function emcmakeGenerateTask() {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function cmakeBuildTask(opts?: {targets?: ReadonlyArray<string>}) {
|
function cmakeBuildTask(opts) {
|
||||||
return () => {
|
return () => {
|
||||||
const cmake = which.sync('cmake');
|
const cmake = which.sync('cmake');
|
||||||
const args = [
|
const args = [
|
||||||
@@ -184,7 +164,7 @@ function cmakeBuildTask(opts?: {targets?: ReadonlyArray<string>}) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function clangFormatTask(opts?: {fix?: boolean}) {
|
function clangFormatTask(opts) {
|
||||||
return () => {
|
return () => {
|
||||||
const args = [
|
const args = [
|
||||||
...(opts?.fix ? ['-i'] : ['--dry-run', '--Werror']),
|
...(opts?.fix ? ['-i'] : ['--dry-run', '--Werror']),
|
@@ -9,69 +9,38 @@
|
|||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "git@github.com:facebook/yoga.git"
|
"url": "git@github.com:facebook/yoga.git"
|
||||||
},
|
},
|
||||||
"exports": {
|
"type": "module",
|
||||||
".": {
|
"main": "./src/index.ts",
|
||||||
"browser": "./src/entrypoint/wasm-async-web.ts",
|
|
||||||
"node": "./src/entrypoint/wasm-async-node.ts",
|
|
||||||
"default": "./src/entrypoint/asmjs-async-web.ts"
|
|
||||||
},
|
|
||||||
"./sync": {
|
|
||||||
"browser": "./src/entrypoint/asmjs-sync-web.ts",
|
|
||||||
"node": "./src/entrypoint/wasm-sync-node.ts",
|
|
||||||
"default": "./src/entrypoint/asmjs-sync-web.ts"
|
|
||||||
},
|
|
||||||
"./asmjs-async": {
|
|
||||||
"browser": "./src/entrypoint/asmjs-async-web.ts",
|
|
||||||
"node": "./src/entrypoint/asmjs-async-node.ts",
|
|
||||||
"default": "./src/entrypoint/asmjs-async-web.ts"
|
|
||||||
},
|
|
||||||
"./asmjs-sync": {
|
|
||||||
"browser": "./src/entrypoint/asmjs-sync-web.ts",
|
|
||||||
"node": "./src/entrypoint/asmjs-sync-node.ts",
|
|
||||||
"default": "./src/entrypoint/asmjs-sync-web.ts"
|
|
||||||
},
|
|
||||||
"./wasm-async": {
|
|
||||||
"browser": "./src/entrypoint/wasm-async-web.ts",
|
|
||||||
"node": "./src/entrypoint/wasm-async-node.ts",
|
|
||||||
"default": "./src/entrypoint/wasm-async-web.ts"
|
|
||||||
},
|
|
||||||
"./wasm-sync": {
|
|
||||||
"browser": "./src/entrypoint/wasm-sync-web.ts",
|
|
||||||
"node": "./src/entrypoint/wasm-sync-node.ts",
|
|
||||||
"default": "./src/entrypoint/wasm-async-web.ts"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"files": [
|
"files": [
|
||||||
"binaries/**",
|
"binaries/**",
|
||||||
"src/**"
|
"src/**"
|
||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"benchmark": "just benchmark",
|
"benchmark": "just benchmark --config just.config.cjs",
|
||||||
"build": "just build",
|
"build": "just build --config just.config.cjs",
|
||||||
"clang-format": "just clang-format",
|
"clang-format": "just clang-format --config just.config.cjs",
|
||||||
"clang-format:fix": "just clang-format --fix",
|
"clang-format:fix": "just clang-format --fix --config just.config.cjs",
|
||||||
"clean": "just clean",
|
"clean": "just clean --config just.config.cjs",
|
||||||
"lint": "eslint .",
|
"lint": "eslint .",
|
||||||
"lint:fix": "eslint . --fix",
|
"lint:fix": "eslint . --fix",
|
||||||
"prepack": "just prepack",
|
"prepack": "just prepack --config just.config.cjs",
|
||||||
"test": "just test",
|
"test": "just test --config just.config.cjs",
|
||||||
"tsc": "tsc --noEmit"
|
"tsc": "tsc --noEmit"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/cli": "^7.21.4",
|
"@babel/cli": "^7.23.0",
|
||||||
"@babel/core": "^7.21.4",
|
"@babel/core": "^7.23.0",
|
||||||
"@babel/node": "^7.21.4",
|
"@babel/preset-env": "^7.23.0",
|
||||||
"@babel/preset-env": "^7.21.4",
|
"@babel/preset-typescript": "^7.23.0",
|
||||||
"@babel/preset-typescript": "^7.21.4",
|
|
||||||
"@types/glob": "^8.1.0",
|
"@types/glob": "^8.1.0",
|
||||||
"@types/jest": "^29.5.1",
|
"@types/jest": "^29.5.1",
|
||||||
"@types/node": "^16.18.25",
|
"@types/node": "^16.18.25",
|
||||||
"@types/which": "^3.0.0",
|
"@types/which": "^3.0.0",
|
||||||
|
"babel-register-esm": "^1.2.5",
|
||||||
"clang-format": "^1.8.0",
|
"clang-format": "^1.8.0",
|
||||||
"glob": "^8.0.3",
|
"glob": "^8.0.3",
|
||||||
"jest": "^29.3.1",
|
"jest": "^29.3.1",
|
||||||
"just-scripts": "^2.1.0",
|
"just-scripts": "^2.1.0",
|
||||||
"ts-node": "^10.9.1",
|
|
||||||
"which": "^3.0.0"
|
"which": "^3.0.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,26 +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 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-node');
|
|
||||||
|
|
||||||
export async function loadYoga(): Promise<Yoga> {
|
|
||||||
return wrapAssembly(await loadAssembly());
|
|
||||||
}
|
|
@@ -1,26 +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 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-web');
|
|
||||||
|
|
||||||
export async function loadYoga(): Promise<Yoga> {
|
|
||||||
return wrapAssembly(await loadAssembly());
|
|
||||||
}
|
|
@@ -1,23 +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 wrapAssembly from '../wrapAssembly';
|
|
||||||
|
|
||||||
export * from '../generated/YGEnums';
|
|
||||||
export type {
|
|
||||||
Config,
|
|
||||||
DirtiedFunction,
|
|
||||||
MeasureFunction,
|
|
||||||
Node,
|
|
||||||
Yoga,
|
|
||||||
} from '../wrapAssembly';
|
|
||||||
|
|
||||||
const loadAssembly = require('../../binaries/asmjs-sync-node');
|
|
||||||
const Yoga = wrapAssembly(loadAssembly());
|
|
||||||
export default Yoga;
|
|
@@ -1,23 +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 wrapAssembly from '../wrapAssembly';
|
|
||||||
|
|
||||||
export * from '../generated/YGEnums';
|
|
||||||
export type {
|
|
||||||
Config,
|
|
||||||
DirtiedFunction,
|
|
||||||
MeasureFunction,
|
|
||||||
Node,
|
|
||||||
Yoga,
|
|
||||||
} from '../wrapAssembly';
|
|
||||||
|
|
||||||
const loadAssembly = require('../../binaries/asmjs-sync-web');
|
|
||||||
const Yoga = wrapAssembly(loadAssembly());
|
|
||||||
export default Yoga;
|
|
@@ -1,26 +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 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-node');
|
|
||||||
|
|
||||||
export async function loadYoga(): Promise<Yoga> {
|
|
||||||
return wrapAssembly(await loadAssembly());
|
|
||||||
}
|
|
@@ -1,26 +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 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-web');
|
|
||||||
|
|
||||||
export async function loadYoga(): Promise<Yoga> {
|
|
||||||
return wrapAssembly(await loadAssembly());
|
|
||||||
}
|
|
@@ -1,23 +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 wrapAssembly from '../wrapAssembly';
|
|
||||||
|
|
||||||
export * from '../generated/YGEnums';
|
|
||||||
export type {
|
|
||||||
Config,
|
|
||||||
DirtiedFunction,
|
|
||||||
MeasureFunction,
|
|
||||||
Node,
|
|
||||||
Yoga,
|
|
||||||
} from '../wrapAssembly';
|
|
||||||
|
|
||||||
const loadAssembly = require('../../binaries/wasm-sync-node');
|
|
||||||
const Yoga = wrapAssembly(loadAssembly());
|
|
||||||
export default Yoga;
|
|
@@ -7,17 +7,17 @@
|
|||||||
* @format
|
* @format
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import wrapAssembly from '../wrapAssembly';
|
// @ts-ignore untyped from Emscripten
|
||||||
|
import loadYoga from '../binaries/web.js';
|
||||||
|
import wrapAssembly from './wrapAssembly.ts';
|
||||||
|
|
||||||
export * from '../generated/YGEnums';
|
|
||||||
export type {
|
export type {
|
||||||
Config,
|
Config,
|
||||||
DirtiedFunction,
|
DirtiedFunction,
|
||||||
MeasureFunction,
|
MeasureFunction,
|
||||||
Node,
|
Node,
|
||||||
Yoga,
|
} from './wrapAssembly.ts';
|
||||||
} from '../wrapAssembly';
|
|
||||||
|
|
||||||
const loadAssembly = require('../../binaries/wasm-sync-web');
|
const Yoga = wrapAssembly(await loadYoga());
|
||||||
const Yoga = wrapAssembly(loadAssembly());
|
|
||||||
export default Yoga;
|
export default Yoga;
|
||||||
|
export * from './generated/YGEnums.ts';
|
@@ -1,146 +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 YGEnums, {Unit, Direction} from './generated/YGEnums';
|
|
||||||
|
|
||||||
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,
|
|
||||||
};
|
|
||||||
}
|
|
@@ -6,10 +6,13 @@
|
|||||||
*
|
*
|
||||||
* @format
|
* @format
|
||||||
*/
|
*/
|
||||||
|
// @ts-nocheck
|
||||||
|
|
||||||
|
import {Unit, Direction} from './generated/YGEnums.ts';
|
||||||
|
import YGEnums from './generated/YGEnums.ts';
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
Align,
|
Align,
|
||||||
Direction,
|
|
||||||
Display,
|
Display,
|
||||||
Edge,
|
Edge,
|
||||||
Errata,
|
Errata,
|
||||||
@@ -20,11 +23,8 @@ import type {
|
|||||||
MeasureMode,
|
MeasureMode,
|
||||||
Overflow,
|
Overflow,
|
||||||
PositionType,
|
PositionType,
|
||||||
Unit,
|
|
||||||
Wrap,
|
Wrap,
|
||||||
} from './generated/YGEnums';
|
} from './generated/YGEnums.ts';
|
||||||
|
|
||||||
import YGEnums from './generated/YGEnums';
|
|
||||||
|
|
||||||
type Layout = {
|
type Layout = {
|
||||||
left: number;
|
left: number;
|
||||||
@@ -179,5 +179,138 @@ export type Yoga = {
|
|||||||
};
|
};
|
||||||
} & typeof YGEnums;
|
} & typeof YGEnums;
|
||||||
|
|
||||||
declare const wrapAsm: (assembly: unknown) => Yoga;
|
export default function wrapAssembly(lib: any): Yoga {
|
||||||
export default wrapAsm;
|
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,
|
||||||
|
};
|
||||||
|
}
|
@@ -5,8 +5,10 @@
|
|||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {getMeasureCounter} from '../tools/MeasureCounter';
|
import {getMeasureCounter} from '../tools/MeasureCounter.ts';
|
||||||
import {Yoga, YGBENCHMARK} from '../tools/globals';
|
import {YGBENCHMARK} from '../tools/globals.ts';
|
||||||
|
|
||||||
|
import Yoga from 'yoga-layout';
|
||||||
|
|
||||||
const ITERATIONS = 2000;
|
const ITERATIONS = 2000;
|
||||||
|
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {Yoga} from './tools/globals';
|
import Yoga from 'yoga-layout';
|
||||||
|
|
||||||
test('align_baseline_parent_using_child_in_column_as_reference', () => {
|
test('align_baseline_parent_using_child_in_column_as_reference', () => {
|
||||||
const config = Yoga.Config.create();
|
const config = Yoga.Config.create();
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {Yoga} from './tools/globals';
|
import Yoga from 'yoga-layout';
|
||||||
|
|
||||||
test('border_start', () => {
|
test('border_start', () => {
|
||||||
const root = Yoga.Node.create();
|
const root = Yoga.Node.create();
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {Yoga} from './tools/globals';
|
import Yoga from 'yoga-layout';
|
||||||
|
|
||||||
test('margin_start', () => {
|
test('margin_start', () => {
|
||||||
const root = Yoga.Node.create();
|
const root = Yoga.Node.create();
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {Yoga} from './tools/globals';
|
import Yoga from 'yoga-layout';
|
||||||
|
|
||||||
test('padding_start', () => {
|
test('padding_start', () => {
|
||||||
const root = Yoga.Node.create();
|
const root = Yoga.Node.create();
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {Yoga} from './tools/globals';
|
import Yoga from 'yoga-layout';
|
||||||
|
|
||||||
test('dirtied', () => {
|
test('dirtied', () => {
|
||||||
const root = Yoga.Node.create();
|
const root = Yoga.Node.create();
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {Yoga} from './tools/globals';
|
import Yoga from 'yoga-layout';
|
||||||
|
|
||||||
test('errata_all_contains_example_errata', () => {
|
test('errata_all_contains_example_errata', () => {
|
||||||
const config = Yoga.Config.create();
|
const config = Yoga.Config.create();
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {Yoga} from './tools/globals';
|
import Yoga from 'yoga-layout';
|
||||||
|
|
||||||
test('flex_basis_auto', () => {
|
test('flex_basis_auto', () => {
|
||||||
const root = Yoga.Node.create();
|
const root = Yoga.Node.create();
|
||||||
|
@@ -5,9 +5,9 @@
|
|||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {Yoga} from './tools/globals';
|
import Yoga from 'yoga-layout';
|
||||||
|
|
||||||
import {getMeasureCounterMax} from './tools/MeasureCounter';
|
import {getMeasureCounterMax} from './tools/MeasureCounter.ts';
|
||||||
|
|
||||||
test('measure_once_single_flexible_child', () => {
|
test('measure_once_single_flexible_child', () => {
|
||||||
const root = Yoga.Node.create();
|
const root = Yoga.Node.create();
|
||||||
|
@@ -5,8 +5,8 @@
|
|||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {Yoga} from './tools/globals';
|
import Yoga from 'yoga-layout';
|
||||||
import {getMeasureCounter} from './tools/MeasureCounter';
|
import {getMeasureCounter} from './tools/MeasureCounter.ts';
|
||||||
|
|
||||||
test('dont_measure_single_grow_shrink_child', () => {
|
test('dont_measure_single_grow_shrink_child', () => {
|
||||||
const root = Yoga.Node.create();
|
const root = Yoga.Node.create();
|
||||||
|
@@ -10,9 +10,6 @@
|
|||||||
|
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
|
|
||||||
import YogaAsmjs from 'yoga-layout/asmjs-sync';
|
|
||||||
import YogaWasm from 'yoga-layout/wasm-sync';
|
|
||||||
|
|
||||||
const WARMUP_ITERATIONS = 3;
|
const WARMUP_ITERATIONS = 3;
|
||||||
const BENCHMARK_ITERATIONS = 10;
|
const BENCHMARK_ITERATIONS = 10;
|
||||||
|
|
||||||
@@ -20,9 +17,7 @@ const testFiles = process.argv.slice(2);
|
|||||||
|
|
||||||
const testResults = new Map<string, Map<string, number>>();
|
const testResults = new Map<string, Map<string, number>>();
|
||||||
|
|
||||||
for (const type of ['asmjs', 'wasm']) {
|
for (const type of ['wasm']) {
|
||||||
globalThis.Yoga = type === 'asmjs' ? YogaAsmjs : YogaWasm;
|
|
||||||
|
|
||||||
for (const file of testFiles) {
|
for (const file of testFiles) {
|
||||||
globalThis.YGBENCHMARK = (name: string, fn: () => void) => {
|
globalThis.YGBENCHMARK = (name: string, fn: () => void) => {
|
||||||
let testEntry = testResults.get(name);
|
let testEntry = testResults.get(name);
|
||||||
@@ -42,10 +37,7 @@ for (const type of ['asmjs', 'wasm']) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const modulePath = path.resolve(file);
|
const modulePath = path.resolve(file);
|
||||||
|
await import(modulePath);
|
||||||
delete require.cache[require.resolve('../tools/globals')];
|
|
||||||
delete require.cache[modulePath];
|
|
||||||
require(modulePath);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
// @generated by gentest/gentest.rb from gentest/fixtures/YGAbsolutePositionTest.html
|
// @generated by gentest/gentest.rb from gentest/fixtures/YGAbsolutePositionTest.html
|
||||||
|
|
||||||
import {Yoga} from "../tools/globals";
|
import Yoga from 'yoga-layout';
|
||||||
import {
|
import {
|
||||||
Align,
|
Align,
|
||||||
Direction,
|
Direction,
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
// @generated by gentest/gentest.rb from gentest/fixtures/YGAlignContentTest.html
|
// @generated by gentest/gentest.rb from gentest/fixtures/YGAlignContentTest.html
|
||||||
|
|
||||||
import {Yoga} from "../tools/globals";
|
import Yoga from 'yoga-layout';
|
||||||
import {
|
import {
|
||||||
Align,
|
Align,
|
||||||
Direction,
|
Direction,
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
// @generated by gentest/gentest.rb from gentest/fixtures/YGAlignItemsTest.html
|
// @generated by gentest/gentest.rb from gentest/fixtures/YGAlignItemsTest.html
|
||||||
|
|
||||||
import {Yoga} from "../tools/globals";
|
import Yoga from 'yoga-layout';
|
||||||
import {
|
import {
|
||||||
Align,
|
Align,
|
||||||
Direction,
|
Direction,
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
// @generated by gentest/gentest.rb from gentest/fixtures/YGAlignSelfTest.html
|
// @generated by gentest/gentest.rb from gentest/fixtures/YGAlignSelfTest.html
|
||||||
|
|
||||||
import {Yoga} from "../tools/globals";
|
import Yoga from 'yoga-layout';
|
||||||
import {
|
import {
|
||||||
Align,
|
Align,
|
||||||
Direction,
|
Direction,
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
// @generated by gentest/gentest.rb from gentest/fixtures/YGAndroidNewsFeed.html
|
// @generated by gentest/gentest.rb from gentest/fixtures/YGAndroidNewsFeed.html
|
||||||
|
|
||||||
import {Yoga} from "../tools/globals";
|
import Yoga from 'yoga-layout';
|
||||||
import {
|
import {
|
||||||
Align,
|
Align,
|
||||||
Direction,
|
Direction,
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
// @generated by gentest/gentest.rb from gentest/fixtures/YGAspectRatioTest.html
|
// @generated by gentest/gentest.rb from gentest/fixtures/YGAspectRatioTest.html
|
||||||
|
|
||||||
import {Yoga} from "../tools/globals";
|
import Yoga from 'yoga-layout';
|
||||||
import {
|
import {
|
||||||
Align,
|
Align,
|
||||||
Direction,
|
Direction,
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
// @generated by gentest/gentest.rb from gentest/fixtures/YGBorderTest.html
|
// @generated by gentest/gentest.rb from gentest/fixtures/YGBorderTest.html
|
||||||
|
|
||||||
import {Yoga} from "../tools/globals";
|
import Yoga from 'yoga-layout';
|
||||||
import {
|
import {
|
||||||
Align,
|
Align,
|
||||||
Direction,
|
Direction,
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
// @generated by gentest/gentest.rb from gentest/fixtures/YGDimensionTest.html
|
// @generated by gentest/gentest.rb from gentest/fixtures/YGDimensionTest.html
|
||||||
|
|
||||||
import {Yoga} from "../tools/globals";
|
import Yoga from 'yoga-layout';
|
||||||
import {
|
import {
|
||||||
Align,
|
Align,
|
||||||
Direction,
|
Direction,
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
// @generated by gentest/gentest.rb from gentest/fixtures/YGDisplayTest.html
|
// @generated by gentest/gentest.rb from gentest/fixtures/YGDisplayTest.html
|
||||||
|
|
||||||
import {Yoga} from "../tools/globals";
|
import Yoga from 'yoga-layout';
|
||||||
import {
|
import {
|
||||||
Align,
|
Align,
|
||||||
Direction,
|
Direction,
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
// @generated by gentest/gentest.rb from gentest/fixtures/YGFlexDirectionTest.html
|
// @generated by gentest/gentest.rb from gentest/fixtures/YGFlexDirectionTest.html
|
||||||
|
|
||||||
import {Yoga} from "../tools/globals";
|
import Yoga from 'yoga-layout';
|
||||||
import {
|
import {
|
||||||
Align,
|
Align,
|
||||||
Direction,
|
Direction,
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
// @generated by gentest/gentest.rb from gentest/fixtures/YGFlexTest.html
|
// @generated by gentest/gentest.rb from gentest/fixtures/YGFlexTest.html
|
||||||
|
|
||||||
import {Yoga} from "../tools/globals";
|
import Yoga from 'yoga-layout';
|
||||||
import {
|
import {
|
||||||
Align,
|
Align,
|
||||||
Direction,
|
Direction,
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
// @generated by gentest/gentest.rb from gentest/fixtures/YGFlexWrapTest.html
|
// @generated by gentest/gentest.rb from gentest/fixtures/YGFlexWrapTest.html
|
||||||
|
|
||||||
import {Yoga} from "../tools/globals";
|
import Yoga from 'yoga-layout';
|
||||||
import {
|
import {
|
||||||
Align,
|
Align,
|
||||||
Direction,
|
Direction,
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
// @generated by gentest/gentest.rb from gentest/fixtures/YGGapTest.html
|
// @generated by gentest/gentest.rb from gentest/fixtures/YGGapTest.html
|
||||||
|
|
||||||
import {Yoga} from "../tools/globals";
|
import Yoga from 'yoga-layout';
|
||||||
import {
|
import {
|
||||||
Align,
|
Align,
|
||||||
Direction,
|
Direction,
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
// @generated by gentest/gentest.rb from gentest/fixtures/YGJustifyContentTest.html
|
// @generated by gentest/gentest.rb from gentest/fixtures/YGJustifyContentTest.html
|
||||||
|
|
||||||
import {Yoga} from "../tools/globals";
|
import Yoga from 'yoga-layout';
|
||||||
import {
|
import {
|
||||||
Align,
|
Align,
|
||||||
Direction,
|
Direction,
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
// @generated by gentest/gentest.rb from gentest/fixtures/YGMarginTest.html
|
// @generated by gentest/gentest.rb from gentest/fixtures/YGMarginTest.html
|
||||||
|
|
||||||
import {Yoga} from "../tools/globals";
|
import Yoga from 'yoga-layout';
|
||||||
import {
|
import {
|
||||||
Align,
|
Align,
|
||||||
Direction,
|
Direction,
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
// @generated by gentest/gentest.rb from gentest/fixtures/YGMinMaxDimensionTest.html
|
// @generated by gentest/gentest.rb from gentest/fixtures/YGMinMaxDimensionTest.html
|
||||||
|
|
||||||
import {Yoga} from "../tools/globals";
|
import Yoga from 'yoga-layout';
|
||||||
import {
|
import {
|
||||||
Align,
|
Align,
|
||||||
Direction,
|
Direction,
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
// @generated by gentest/gentest.rb from gentest/fixtures/YGPaddingTest.html
|
// @generated by gentest/gentest.rb from gentest/fixtures/YGPaddingTest.html
|
||||||
|
|
||||||
import {Yoga} from "../tools/globals";
|
import Yoga from 'yoga-layout';
|
||||||
import {
|
import {
|
||||||
Align,
|
Align,
|
||||||
Direction,
|
Direction,
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
// @generated by gentest/gentest.rb from gentest/fixtures/YGPercentageTest.html
|
// @generated by gentest/gentest.rb from gentest/fixtures/YGPercentageTest.html
|
||||||
|
|
||||||
import {Yoga} from "../tools/globals";
|
import Yoga from 'yoga-layout';
|
||||||
import {
|
import {
|
||||||
Align,
|
Align,
|
||||||
Direction,
|
Direction,
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
// @generated by gentest/gentest.rb from gentest/fixtures/YGRoundingTest.html
|
// @generated by gentest/gentest.rb from gentest/fixtures/YGRoundingTest.html
|
||||||
|
|
||||||
import {Yoga} from "../tools/globals";
|
import Yoga from 'yoga-layout';
|
||||||
import {
|
import {
|
||||||
Align,
|
Align,
|
||||||
Direction,
|
Direction,
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
// @generated by gentest/gentest.rb from gentest/fixtures/YGSizeOverflowTest.html
|
// @generated by gentest/gentest.rb from gentest/fixtures/YGSizeOverflowTest.html
|
||||||
|
|
||||||
import {Yoga} from "../tools/globals";
|
import Yoga from 'yoga-layout';
|
||||||
import {
|
import {
|
||||||
Align,
|
Align,
|
||||||
Direction,
|
Direction,
|
||||||
|
@@ -8,7 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import type {MeasureFunction} from 'yoga-layout';
|
import type {MeasureFunction} from 'yoga-layout';
|
||||||
import {Yoga} from './globals';
|
import Yoga from 'yoga-layout';
|
||||||
|
|
||||||
export type MeasureCounter = {
|
export type MeasureCounter = {
|
||||||
inc: MeasureFunction;
|
inc: MeasureFunction;
|
||||||
|
@@ -5,23 +5,15 @@
|
|||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type {Yoga} from 'yoga-layout';
|
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
// eslint-disable-next-line no-var
|
|
||||||
var Yoga: Yoga | undefined;
|
|
||||||
// eslint-disable-next-line no-var
|
// eslint-disable-next-line no-var
|
||||||
var YGBENCHMARK: (title: string, fn: () => void) => void;
|
var YGBENCHMARK: (title: string, fn: () => void) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (globalThis.Yoga === undefined) {
|
|
||||||
throw new Error('Expected "Yoga" global to be set');
|
|
||||||
}
|
|
||||||
if (globalThis.YGBENCHMARK === undefined) {
|
if (globalThis.YGBENCHMARK === undefined) {
|
||||||
throw new Error('Expected "YGBENCHMARK" global to be set');
|
throw new Error('Expected "YGBENCHMARK" global to be set');
|
||||||
}
|
}
|
||||||
|
|
||||||
const yoga = globalThis.Yoga;
|
|
||||||
const benchmark = globalThis.YGBENCHMARK;
|
const benchmark = globalThis.YGBENCHMARK;
|
||||||
|
|
||||||
export {yoga as Yoga, benchmark as YGBENCHMARK};
|
export {benchmark as YGBENCHMARK};
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "es2018",
|
"target": "es2020",
|
||||||
"module": "commonjs",
|
"module": "esnext",
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"declaration": true,
|
"declaration": true,
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
@@ -11,15 +11,13 @@
|
|||||||
"forceConsistentCasingInFileNames": false,
|
"forceConsistentCasingInFileNames": false,
|
||||||
"baseUrl": ".",
|
"baseUrl": ".",
|
||||||
"moduleResolution": "nodenext",
|
"moduleResolution": "nodenext",
|
||||||
|
"allowImportingTsExtensions": true,
|
||||||
"paths": {
|
"paths": {
|
||||||
"yoga-layout": ["src"]
|
"yoga-layout": ["src"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ts-node": {
|
"include": [
|
||||||
"transpileOnly": true
|
"src/**/*",
|
||||||
},
|
"tests/**/*"
|
||||||
"exclude": [
|
|
||||||
"binaries/**/*",
|
|
||||||
"build/**/*"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@@ -37,7 +37,7 @@ const config = {
|
|||||||
/** @type {import('@docusaurus/preset-classic').Options} */
|
/** @type {import('@docusaurus/preset-classic').Options} */
|
||||||
({
|
({
|
||||||
docs: {
|
docs: {
|
||||||
sidebarPath: require.resolve('./sidebars.js'),
|
sidebarPath: require.resolve('./sidebars.cjs'),
|
||||||
editUrl: 'https://github.com/facebook/yoga/tree/main/website',
|
editUrl: 'https://github.com/facebook/yoga/tree/main/website',
|
||||||
},
|
},
|
||||||
blog: {
|
blog: {
|
@@ -11,7 +11,7 @@ import React, {Component} from 'react';
|
|||||||
import {Row, Col, Button, Tabs} from 'antd';
|
import {Row, Col, Button, Tabs} from 'antd';
|
||||||
import EditValue from './EditValue';
|
import EditValue from './EditValue';
|
||||||
import type {LayoutRecordType} from './LayoutRecord';
|
import type {LayoutRecordType} from './LayoutRecord';
|
||||||
import type {Direction} from 'yoga-layout/sync';
|
import type {Direction} from 'yoga-layout';
|
||||||
import InfoText from './InfoText';
|
import InfoText from './InfoText';
|
||||||
import './Editor.css';
|
import './Editor.css';
|
||||||
const TabPane = Tabs.TabPane;
|
const TabPane = Tabs.TabPane;
|
||||||
|
@@ -10,15 +10,8 @@
|
|||||||
import {Record, List} from 'immutable';
|
import {Record, List} from 'immutable';
|
||||||
import PositionRecord from './PositionRecord';
|
import PositionRecord from './PositionRecord';
|
||||||
import type {PositionRecordType} from './PositionRecord';
|
import type {PositionRecordType} from './PositionRecord';
|
||||||
import yoga from 'yoga-layout/sync';
|
|
||||||
|
|
||||||
import type {
|
import {Align, Justify, FlexDirection, Wrap, PositionType} from 'yoga-layout';
|
||||||
Align,
|
|
||||||
Justify,
|
|
||||||
FlexDirection,
|
|
||||||
Wrap,
|
|
||||||
PositionType,
|
|
||||||
} from 'yoga-layout/sync';
|
|
||||||
|
|
||||||
export type LayoutRecordType = ReturnType<LayoutRecordFactory>;
|
export type LayoutRecordType = ReturnType<LayoutRecordFactory>;
|
||||||
|
|
||||||
@@ -50,11 +43,11 @@ export type LayoutRecordFactory = Record.Factory<{
|
|||||||
const r: LayoutRecordFactory = Record({
|
const r: LayoutRecordFactory = Record({
|
||||||
width: 'auto',
|
width: 'auto',
|
||||||
height: 'auto',
|
height: 'auto',
|
||||||
justifyContent: yoga.JUSTIFY_FLEX_START,
|
justifyContent: Justify.FlexStart,
|
||||||
alignItems: yoga.ALIGN_STRETCH,
|
alignItems: Align.Stretch,
|
||||||
alignSelf: yoga.ALIGN_AUTO,
|
alignSelf: Align.Auto,
|
||||||
alignContent: yoga.ALIGN_STRETCH,
|
alignContent: Align.Stretch,
|
||||||
flexDirection: yoga.FLEX_DIRECTION_ROW,
|
flexDirection: FlexDirection.Row,
|
||||||
padding: PositionRecord(),
|
padding: PositionRecord(),
|
||||||
margin: PositionRecord(),
|
margin: PositionRecord(),
|
||||||
border: PositionRecord(),
|
border: PositionRecord(),
|
||||||
@@ -64,8 +57,8 @@ const r: LayoutRecordFactory = Record({
|
|||||||
right: NaN,
|
right: NaN,
|
||||||
bottom: NaN,
|
bottom: NaN,
|
||||||
}),
|
}),
|
||||||
positionType: yoga.POSITION_TYPE_RELATIVE,
|
positionType: PositionType.Relative,
|
||||||
flexWrap: yoga.WRAP_NO_WRAP,
|
flexWrap: Wrap.NoWrap,
|
||||||
flexBasis: 'auto',
|
flexBasis: 'auto',
|
||||||
flexGrow: 0,
|
flexGrow: 0,
|
||||||
flexShrink: 1,
|
flexShrink: 1,
|
||||||
|
@@ -8,7 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import React, {Component} from 'react';
|
import React, {Component} from 'react';
|
||||||
import Yoga from 'yoga-layout/sync';
|
import Yoga from 'yoga-layout';
|
||||||
import {Radio, Menu, Dropdown, Button, Icon} from 'antd';
|
import {Radio, Menu, Dropdown, Button, Icon} from 'antd';
|
||||||
import './YogaEnumSelect.css';
|
import './YogaEnumSelect.css';
|
||||||
const RadioButton = Radio.Button;
|
const RadioButton = Radio.Button;
|
||||||
|
@@ -8,12 +8,12 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import React, {Component} from 'react';
|
import React, {Component} from 'react';
|
||||||
import Yoga from 'yoga-layout/sync';
|
import Yoga from 'yoga-layout';
|
||||||
import PositionGuide from './PositionGuide';
|
import PositionGuide from './PositionGuide';
|
||||||
import PositionRecord from './PositionRecord';
|
import PositionRecord from './PositionRecord';
|
||||||
import LayoutRecord from './LayoutRecord';
|
import LayoutRecord from './LayoutRecord';
|
||||||
import type {LayoutRecordType} from './LayoutRecord';
|
import type {LayoutRecordType} from './LayoutRecord';
|
||||||
import {Direction, Display, Edge, Node, Wrap} from 'yoga-layout/sync';
|
import {Direction, Display, Edge, Node, Wrap} from 'yoga-layout';
|
||||||
|
|
||||||
import './YogaNode.css';
|
import './YogaNode.css';
|
||||||
|
|
||||||
|
@@ -5,19 +5,14 @@
|
|||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.PlaygroundContainer {
|
.PlaygroundContainer {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.Playground {
|
.playground-background {
|
||||||
display: flex;
|
|
||||||
flex-grow: 1;
|
|
||||||
position: relative;
|
|
||||||
width: 100%;
|
|
||||||
overflow: hidden;
|
|
||||||
background: linear-gradient(-90deg, rgba(0, 0, 0, 0.02) 1px, transparent 1px),
|
background: linear-gradient(-90deg, rgba(0, 0, 0, 0.02) 1px, transparent 1px),
|
||||||
linear-gradient(rgba(0, 0, 0, 0.02) 1px, transparent 1px),
|
linear-gradient(rgba(0, 0, 0, 0.02) 1px, transparent 1px),
|
||||||
linear-gradient(-90deg, rgba(0, 0, 0, 0.03) 1px, transparent 1px),
|
linear-gradient(-90deg, rgba(0, 0, 0, 0.03) 1px, transparent 1px),
|
||||||
@@ -41,6 +36,15 @@
|
|||||||
100px 100px, 100px 100px, 100px 100px;
|
100px 100px, 100px 100px, 100px 100px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.Playground {
|
||||||
|
display: flex;
|
||||||
|
flex-grow: 1;
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
animation: playground-content-fade-in-frames 50ms ease-in;
|
||||||
|
}
|
||||||
|
|
||||||
.Playground > .YogaNode {
|
.Playground > .YogaNode {
|
||||||
margin: auto;
|
margin: auto;
|
||||||
position: static;
|
position: static;
|
||||||
@@ -72,3 +76,12 @@
|
|||||||
.ant-modal-content {
|
.ant-modal-content {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@keyframes playground-content-fade-in-frames {
|
||||||
|
0% {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -8,7 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import React, {Component} from 'react';
|
import React, {Component} from 'react';
|
||||||
import {Direction} from 'yoga-layout/sync';
|
import {Direction} from 'yoga-layout';
|
||||||
import YogaNode from './YogaNode';
|
import YogaNode from './YogaNode';
|
||||||
import Editor from './Editor';
|
import Editor from './Editor';
|
||||||
import {List, setIn} from 'immutable';
|
import {List, setIn} from 'immutable';
|
||||||
@@ -235,52 +235,58 @@ export default class Playground extends Component<Props, State> {
|
|||||||
: null;
|
: null;
|
||||||
|
|
||||||
const playground = (
|
const playground = (
|
||||||
<div
|
<div className="playground-background">
|
||||||
className={`Playground ${this.props.renderSidebar ? '' : 'standalone'}`}
|
<div
|
||||||
onMouseDown={this.onMouseDown}
|
className={`Playground ${
|
||||||
style={{height, maxHeight: height}}
|
this.props.renderSidebar ? '' : 'standalone'
|
||||||
ref={ref => {
|
}`}
|
||||||
this._containerRef = ref;
|
onMouseDown={this.onMouseDown}
|
||||||
}}>
|
style={{height, maxHeight: height}}
|
||||||
<YogaNode
|
ref={ref => {
|
||||||
layoutDefinition={layoutDefinition}
|
this._containerRef = ref;
|
||||||
selectedNodePath={selectedNodePath}
|
}}>
|
||||||
onClick={selectedNodePath => this.setState({selectedNodePath})}
|
<YogaNode
|
||||||
onDoubleClick={this.onAdd}
|
layoutDefinition={layoutDefinition}
|
||||||
direction={direction}
|
selectedNodePath={selectedNodePath}
|
||||||
showGuides={this.props.showGuides}
|
onClick={selectedNodePath => this.setState({selectedNodePath})}
|
||||||
/>
|
onDoubleClick={this.onAdd}
|
||||||
{!this.props.renderSidebar && (
|
direction={direction}
|
||||||
<Sidebar>
|
showGuides={this.props.showGuides}
|
||||||
{this.state.selectedNodePath ? (
|
/>
|
||||||
<Editor
|
{!this.props.renderSidebar && (
|
||||||
node={selectedNode}
|
<Sidebar>
|
||||||
selectedNodeIsRoot={
|
{this.state.selectedNodePath ? (
|
||||||
selectedNodePath ? selectedNodePath.length === 0 : false
|
<Editor
|
||||||
}
|
node={selectedNode}
|
||||||
onChangeLayout={this.onChangeLayout}
|
selectedNodeIsRoot={
|
||||||
// @ts-ignore
|
selectedNodePath ? selectedNodePath.length === 0 : false
|
||||||
onChangeSetting={(key, value) => this.setState({[key]: value})}
|
}
|
||||||
direction={direction}
|
onChangeLayout={this.onChangeLayout}
|
||||||
onRemove={
|
// @ts-ignore
|
||||||
selectedNodePath && selectedNodePath.length > 0
|
onChangeSetting={(key, value) =>
|
||||||
? this.onRemove
|
this.setState({[key]: value})
|
||||||
: undefined
|
}
|
||||||
}
|
direction={direction}
|
||||||
onAdd={
|
onRemove={
|
||||||
selectedNodePath &&
|
selectedNodePath && selectedNodePath.length > 0
|
||||||
selectedNodePath.length < this.props.maxDepth
|
? this.onRemove
|
||||||
? this.onAdd
|
: undefined
|
||||||
: undefined
|
}
|
||||||
}
|
onAdd={
|
||||||
/>
|
selectedNodePath &&
|
||||||
) : (
|
selectedNodePath.length < this.props.maxDepth
|
||||||
<div className="NoContent">
|
? this.onAdd
|
||||||
Select a node to edit its properties
|
: undefined
|
||||||
</div>
|
}
|
||||||
)}
|
/>
|
||||||
</Sidebar>
|
) : (
|
||||||
)}
|
<div className="NoContent">
|
||||||
|
Select a node to edit its properties
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Sidebar>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@@ -28,3 +28,29 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.playgroundFallback {
|
||||||
|
height: 500px;
|
||||||
|
width: 100%;
|
||||||
|
background: linear-gradient(-90deg, rgba(0, 0, 0, 0.02) 1px, transparent 1px),
|
||||||
|
linear-gradient(rgba(0, 0, 0, 0.02) 1px, transparent 1px),
|
||||||
|
linear-gradient(-90deg, rgba(0, 0, 0, 0.03) 1px, transparent 1px),
|
||||||
|
linear-gradient(rgba(0, 0, 0, 0.03) 1px, transparent 1px),
|
||||||
|
linear-gradient(
|
||||||
|
transparent 4px,
|
||||||
|
#f5f5f5 4px,
|
||||||
|
#f5f5f5 97px,
|
||||||
|
transparent 97px
|
||||||
|
),
|
||||||
|
linear-gradient(-90deg, #e5e5e5 1px, transparent 1px),
|
||||||
|
linear-gradient(
|
||||||
|
-90deg,
|
||||||
|
transparent 4px,
|
||||||
|
#f5f5f5 4px,
|
||||||
|
#f5f5f5 97px,
|
||||||
|
transparent 97px
|
||||||
|
),
|
||||||
|
linear-gradient(#e5e5e5 1px, transparent 1px), #f5f5f5;
|
||||||
|
background-size: 10px 10px, 10px 10px, 100px 100px, 100px 100px, 100px 100px,
|
||||||
|
100px 100px, 100px 100px, 100px 100px;
|
||||||
|
}
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React, {Suspense} from 'react';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import Link from '@docusaurus/Link';
|
import Link from '@docusaurus/Link';
|
||||||
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
||||||
@@ -34,6 +34,22 @@ function HomepageHeader() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const LazyPlayground = React.lazy(() => import('../components/Playground'));
|
||||||
|
|
||||||
|
function ClientPlayground() {
|
||||||
|
const fallback = <div className={styles.playgroundFallback} />;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<BrowserOnly fallback={fallback}>
|
||||||
|
{() => (
|
||||||
|
<Suspense fallback={fallback}>
|
||||||
|
<LazyPlayground />
|
||||||
|
</Suspense>
|
||||||
|
)}
|
||||||
|
</BrowserOnly>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export default function Home(): JSX.Element {
|
export default function Home(): JSX.Element {
|
||||||
const {siteConfig} = useDocusaurusContext();
|
const {siteConfig} = useDocusaurusContext();
|
||||||
return (
|
return (
|
||||||
@@ -43,12 +59,7 @@ export default function Home(): JSX.Element {
|
|||||||
<HomepageHeader />
|
<HomepageHeader />
|
||||||
<main>
|
<main>
|
||||||
<HomepageFeatures />
|
<HomepageFeatures />
|
||||||
<BrowserOnly fallback={null}>
|
<ClientPlayground />
|
||||||
{() => {
|
|
||||||
const Playground = require('../components/Playground');
|
|
||||||
return <Playground />;
|
|
||||||
}}
|
|
||||||
</BrowserOnly>
|
|
||||||
</main>
|
</main>
|
||||||
</Layout>
|
</Layout>
|
||||||
);
|
);
|
||||||
|
@@ -2,6 +2,10 @@
|
|||||||
// This file is not used in compilation. It is here just for a nice editor experience.
|
// This file is not used in compilation. It is here just for a nice editor experience.
|
||||||
"extends": "@tsconfig/docusaurus/tsconfig.json",
|
"extends": "@tsconfig/docusaurus/tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"baseUrl": "."
|
"baseUrl": ".",
|
||||||
|
"target": "esnext",
|
||||||
|
"module": "esnext",
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"allowImportingTsExtensions": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user