Revive JavaScript Bindings (#1177)

Summary:
Yoga's JavaScript bindings do not work past Node 10, or on recent versions of Ubuntu even using it. This is due to a reliance on `nbind`, a library which is no longer maintained. `nbind` itself abstracts over `embind` running Emscripten to generate an asm.js build, along with building Node native modules. In the meantime, [yoga-layout-prebuilt](https://www.npmjs.com/package/yoga-layout-prebuilt) has been used by the community instead of the official package.

https://github.com/facebook/yoga/pull/1177 was contributed as a conversion of bindings created using `nbind` to instead use `embind` directly.

I continued building on this to add more:
1. WebAssembly support (required to be async in browsers)
2. CMake + Ninja Build for the 4 flavors
3. TypeScript typings (partially generated)
4. yarn scripts to build (working on macOS, Ubuntu, Windows)
5. A README with some usage and contribution instructions
6. Updated tests to work with Jest, and updated general infra
7. ESLint and clang-format scripts
8. More GitHub actions (and now testing Windows)
9. Probably more I kinda got carried away here lol

The plan is to eventually publish this to NPM, but there is a little bit of work after this before that happens.

Pull Request resolved: https://github.com/facebook/yoga/pull/1177

Test Plan: The bindings pass Jest tests (both manual and generated). GitHub actions added for the different yarn scripts. Did some manual checks on using the library as TS.

Reviewed By: christophpurrer

Differential Revision: D42207782

Pulled By: NickGerleman

fbshipit-source-id: 1dc5ce440f1c2b9705a005bbdcc86f952785d94e
This commit is contained in:
Dmitry Ivakhnenko
2022-12-28 01:27:12 -08:00
committed by Facebook GitHub Bot
parent 8035456330
commit 1813748eaa
110 changed files with 24702 additions and 22470 deletions

View File

@@ -222,38 +222,56 @@ for name, values in sorted(ENUMS.items()):
f.write("}\n")
# write out javascript file
with open(root + "/javascript/sources/YGEnums.js", "w") as f:
with open(root + "/javascript/src_js/generated/YGEnums.js", "w") as f:
f.write(get_license("js"))
f.write("// @flow\n")
f.write("// @format\n")
f.write("const CONSTANTS = {\n")
f.write("module.exports = {\n")
items = sorted(ENUMS.items())
for name, values in items:
f.write(" %s_COUNT: %s,\n" % (to_java_upper(name), len(values)))
base = 0
for value in values:
if isinstance(value, tuple):
f.write(
" %s_%s: %d,\n"
% (to_java_upper(name), to_java_upper(value[0]), value[1])
)
base = value[1] + 1
else:
f.write(
" %s_%s: %d,\n" % (to_java_upper(name), to_java_upper(value), base)
)
base += 1
value_arg = value[0] if isinstance(value, tuple) else value
ordinal_arg = value[1] if isinstance(value, tuple) else base
f.write(
" %s_%s: %d,\n"
% (to_java_upper(name), to_java_upper(value_arg), ordinal_arg)
)
base = ordinal_arg + 1
if name != items[-1][0]:
f.write("\n")
f.write("};\n")
with open(root + "/javascript/src_js/generated/YGEnums.d.ts", "w") as f:
f.write(get_license("js"))
for name, values in sorted(ENUMS.items()):
f.write("export type Yoga${} =\n".format(name))
base = 0
for value in values:
value_arg = value[0] if isinstance(value, tuple) else value
ordinal_arg = value[1] if isinstance(value, tuple) else base
f.write(
(
"type {name}_{value} = {ordinal} & ['{name}']\n"
+ "export const {name}_{value}: {name}_{value};\n\n"
).format(
name=to_java_upper(name),
value=to_java_upper(value_arg),
ordinal=ordinal_arg,
)
)
base = ordinal_arg + 1
f.write("\n")
for name, values in sorted(ENUMS.items()):
f.write("export type {} =\n".format(name))
for value in values:
unpackedValue = value[0] if isinstance(value, tuple) else value
f.write(
" | typeof CONSTANTS.{}_{}".format(
" | typeof {}_{}".format(
to_java_upper(name), to_java_upper(unpackedValue)
)
)
@@ -263,4 +281,3 @@ with open(root + "/javascript/sources/YGEnums.js", "w") as f:
f.write("\n")
f.write("\n")
f.write("module.exports = CONSTANTS;\n")