Skip to content

Commit 92fb9e5

Browse files
authored
[wasm] Enable execution in node (#2520)
Make the WASM backend work in node. Also: - Enable node tests in CI - Reduce log outputs when running tests in core. - Fix #1497 (comment) (tfjs_backend_wasm.default is not a fuction) - Remove pre-install script which causes yarn of a third-party project that uses the wasm backend to spin indefinitely. FEATURE
1 parent 3c8406d commit 92fb9e5

22 files changed

+206
-75
lines changed

tfjs-backend-wasm/cloudbuild.yml

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,23 +13,31 @@ steps:
1313
args: ['install']
1414
waitFor: ['yarn-common']
1515

16+
# Build core from master.
17+
- name: 'node:10'
18+
dir: 'tfjs-backend-wasm'
19+
id: 'build-core'
20+
entrypoint: 'yarn'
21+
args: ['build-core']
22+
waitFor: ['yarn-common']
23+
1624
# Run lint.
1725
- name: 'node:10'
1826
dir: 'tfjs-backend-wasm'
1927
entrypoint: 'yarn'
2028
id: 'lint'
2129
args: ['lint']
22-
waitFor: ['yarn']
30+
waitFor: ['build-core']
2331

2432
# Build the project.
2533
- name: 'node:10'
2634
dir: 'tfjs-backend-wasm'
2735
entrypoint: 'yarn'
2836
id: 'build'
2937
args: ['build-ci']
30-
waitFor: ['yarn']
38+
waitFor: ['build-core']
3139

32-
# Run browser tests.
40+
# Run tests in browser.
3341
- name: 'node:10'
3442
dir: 'tfjs-backend-wasm'
3543
entrypoint: 'yarn'
@@ -39,6 +47,14 @@ steps:
3947
env: ['BROWSERSTACK_USERNAME=deeplearnjs1']
4048
secretEnv: ['BROWSERSTACK_KEY']
4149

50+
# Run tests in node.
51+
- name: 'node:10'
52+
dir: 'tfjs-backend-wasm'
53+
entrypoint: 'yarn'
54+
id: 'test-node'
55+
args: ['test-node']
56+
waitFor: ['build']
57+
4258
# Run C++ tests.
4359
- name: 'node:10'
4460
dir: 'tfjs-backend-wasm'

tfjs-backend-wasm/karma.conf.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ module.exports = function(config) {
5454
// Import the rest of the sources.
5555
{pattern: 'src/**/*.ts'},
5656
],
57+
exclude: ['src/test_node.ts'],
5758
preprocessors: {
5859
'wasm-out/**/*.js': ['karma-typescript'],
5960
'**/*.ts': ['karma-typescript']

tfjs-backend-wasm/package.json

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,16 @@
88
"unpkg": "dist/tf-wasm.min.js",
99
"jsdelivr": "dist/tf-wasm.min.js",
1010
"scripts": {
11-
"preinstall": "cd ../tfjs-core && yarn && yarn build",
12-
"build": "rimraf dist/ && yarn link-core-master && tsc && ./scripts/build-wasm.sh",
11+
"build-core": "yarn link-core-master && cd ../tfjs-core && yarn && yarn build",
12+
"build": "yarn build-core && rimraf dist/ && tsc && ./scripts/build-wasm.sh",
1313
"build-ci": "./scripts/build-ci.sh",
1414
"build-npm": "./scripts/build-npm.sh",
1515
"clean": "rimraf dist/ && bazel clean --expunge",
1616
"cpplint": "./scripts/cpplint.js",
1717
"lint": "tslint -p . -t verbose && yarn cpplint",
1818
"link-core-master": "./scripts/link-core-master.js",
1919
"test": "yarn link-core-master && ./scripts/build-wasm.sh && karma start",
20+
"test-node": "ts-node src/test_node.ts",
2021
"test-bundle-size": "./scripts/test-bundle-size.js",
2122
"test-cc": "bazel test //src/cc:cc_tests --test_output=all",
2223
"test-browser-ci": "karma start --singleRun --browsers=bs_chrome_mac"
@@ -29,7 +30,8 @@
2930
"@tensorflow/tfjs-core": "link:../tfjs-core",
3031
"@types/emscripten": "~0.0.34",
3132
"@types/jasmine": "~2.8.6",
32-
"clang-format": "^1.2.4",
33+
"clang-format": "~1.2.4",
34+
"jasmine": "~3.1.0",
3335
"jasmine-core": "~3.1.0",
3436
"karma": "~4.0.0",
3537
"karma-browserstack-launcher": "~1.4.0",
@@ -41,10 +43,11 @@
4143
"rollup": "~1.26.3",
4244
"rollup-plugin-commonjs": "~10.1.0",
4345
"rollup-plugin-node-resolve": "~5.2.0",
44-
"rollup-plugin-terser": "^5.1.1",
46+
"rollup-plugin-terser": "~5.1.1",
4547
"rollup-plugin-typescript2": "~0.25.2",
46-
"tslint": "^5.20.0",
47-
"tslint-no-circular-imports": "^0.7.0",
48+
"ts-node": "~8.5.4",
49+
"tslint": "~5.20.0",
50+
"tslint-no-circular-imports": "~0.7.0",
4851
"typescript": "3.5.3",
4952
"yalc": "~1.0.0-pre.21"
5053
},

tfjs-backend-wasm/rollup.config.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ module.exports = cmdOptions => {
7878
bundles.push(config({
7979
output: {
8080
format: 'umd',
81-
name: 'tf',
81+
name: 'tf.wasm',
8282
extend: true,
8383
file: 'dist/tf-backend-wasm.js',
8484
}
@@ -90,7 +90,7 @@ module.exports = cmdOptions => {
9090
plugins: [terser({output: {preamble: PREAMBLE}})],
9191
output: {
9292
format: 'umd',
93-
name: 'tf',
93+
name: 'tf.wasm',
9494
extend: true,
9595
file: 'dist/tf-backend-wasm.min.js',
9696
},

tfjs-backend-wasm/src/cc/BUILD

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ cc_binary(
1818
"-s EXIT_RUNTIME=0",
1919
"-s EXPORTED_FUNCTIONS='[\"_malloc\", \"_free\"]'",
2020
"-s EXTRA_EXPORTED_RUNTIME_METHODS='[\"cwrap\"]'",
21-
"-s ENVIRONMENT=web",
2221
"-s MODULARIZE=1",
2322
"-s EXPORT_NAME=WasmBackendModule",
2423
"-s MALLOC=emmalloc",

tfjs-backend-wasm/src/test_node.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/**
2+
* @license
3+
* Copyright 2018 Google LLC. All Rights Reserved.
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
* =============================================================================
16+
*/
17+
18+
// Register the wasm backend.
19+
import './index';
20+
21+
// tslint:disable-next-line: no-imports-from-dist
22+
import {setTestEnvs} from '@tensorflow/tfjs-core/dist/jasmine_util';
23+
import jasmine from 'jasmine';
24+
25+
Error.stackTraceLimit = Infinity;
26+
27+
process.on('unhandledRejection', e => {
28+
throw e;
29+
});
30+
31+
setTestEnvs([{name: 'wasm-node', backendName: 'wasm', isDataSync: true}]);
32+
33+
const runner = new jasmine({});
34+
runner.loadConfig({spec_files: ['src/**/*_test.ts'], random: false});
35+
36+
if (process.env.JASMINE_SEED) {
37+
runner.seed(process.env.JASMINE_SEED);
38+
}
39+
40+
runner.execute();

tfjs-backend-wasm/tsconfig.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"node_modules/"
88
],
99
"compilerOptions": {
10+
"esModuleInterop": true,
1011
"outDir": "./dist"
1112
}
1213
}

tfjs-backend-wasm/yarn.lock

Lines changed: 61 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,11 @@ are-we-there-yet@~1.1.2:
200200
delegates "^1.0.0"
201201
readable-stream "^2.0.6"
202202

203+
arg@^4.1.0:
204+
version "4.1.2"
205+
resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.2.tgz#e70c90579e02c63d80e3ad4e31d8bfdb8bd50064"
206+
integrity sha512-+ytCkGcBtHZ3V2r2Z06AncYO8jz46UEamcspGoU8lHcEbpn6J77QK0vdWvChsclg/tM5XIJC5tnjmPp7Eq6Obg==
207+
203208
argparse@^1.0.7:
204209
version "1.0.10"
205210
resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911"
@@ -647,7 +652,7 @@ cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3:
647652
inherits "^2.0.1"
648653
safe-buffer "^5.0.1"
649654

650-
clang-format@^1.2.4:
655+
clang-format@~1.2.4:
651656
version "1.2.4"
652657
resolved "https://registry.yarnpkg.com/clang-format/-/clang-format-1.2.4.tgz#4bb4b0a98180428deb093cf20982e9fc1af20b6c"
653658
integrity sha512-sw+nrGUp3hvmANd1qF8vZPuezSYQAiXgGBiEtkXTtJnnu6b00fCqkkDIsnRKrNgg4nv6NYZE92ejvOMIXZoejw==
@@ -1429,6 +1434,18 @@ glob@^7.0.0, glob@^7.1.1, glob@^7.1.3, glob@^7.1.4:
14291434
once "^1.3.0"
14301435
path-is-absolute "^1.0.0"
14311436

1437+
glob@^7.0.6:
1438+
version "7.1.6"
1439+
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6"
1440+
integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==
1441+
dependencies:
1442+
fs.realpath "^1.0.0"
1443+
inflight "^1.0.4"
1444+
inherits "2"
1445+
minimatch "^3.0.4"
1446+
once "^1.3.0"
1447+
path-is-absolute "^1.0.0"
1448+
14321449
graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0:
14331450
version "4.2.2"
14341451
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.2.tgz#6f0952605d0140c1cfdb138ed005775b92d67b02"
@@ -1850,6 +1867,14 @@ jasmine-core@~3.1.0:
18501867
resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-3.1.0.tgz#a4785e135d5df65024dfc9224953df585bd2766c"
18511868
integrity sha1-pHheE11d9lAk38kiSVPfWFvSdmw=
18521869

1870+
jasmine@~3.1.0:
1871+
version "3.1.0"
1872+
resolved "https://registry.yarnpkg.com/jasmine/-/jasmine-3.1.0.tgz#2bd59fd7ec6ec0e8acb64e09f45a68ed2ad1952a"
1873+
integrity sha1-K9Wf1+xuwOistk4J9Fpo7SrRlSo=
1874+
dependencies:
1875+
glob "^7.0.6"
1876+
jasmine-core "~3.1.0"
1877+
18531878
jest-worker@^24.6.0:
18541879
version "24.9.0"
18551880
resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-24.9.0.tgz#5dbfdb5b2d322e98567898238a9697bcce67b3e5"
@@ -2114,6 +2139,11 @@ make-dir@^3.0.0:
21142139
dependencies:
21152140
semver "^6.0.0"
21162141

2142+
make-error@^1.1.1:
2143+
version "1.3.5"
2144+
resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.5.tgz#efe4e81f6db28cadd605c70f29c831b58ef776c8"
2145+
integrity sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==
2146+
21172147
map-cache@^0.2.2:
21182148
version "0.2.2"
21192149
resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf"
@@ -2966,7 +2996,7 @@ rollup-plugin-node-resolve@~5.2.0:
29662996
resolve "^1.11.1"
29672997
rollup-pluginutils "^2.8.1"
29682998

2969-
rollup-plugin-terser@^5.1.1:
2999+
rollup-plugin-terser@~5.1.1:
29703000
version "5.1.2"
29713001
resolved "https://registry.yarnpkg.com/rollup-plugin-terser/-/rollup-plugin-terser-5.1.2.tgz#3e41256205cb75f196fc70d4634227d1002c255c"
29723002
integrity sha512-sWKBCOS+vUkRtHtEiJPAf+WnBqk/C402fBD9AVHxSIXMqjsY7MnYWKYEUqGixtr0c8+1DjzUEPlNgOYQPVrS1g==
@@ -3183,6 +3213,14 @@ source-map-resolve@^0.5.0:
31833213
source-map-url "^0.4.0"
31843214
urix "^0.1.0"
31853215

3216+
source-map-support@^0.5.6:
3217+
version "0.5.16"
3218+
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.16.tgz#0ae069e7fe3ba7538c64c98515e35339eac5a042"
3219+
integrity sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ==
3220+
dependencies:
3221+
buffer-from "^1.0.0"
3222+
source-map "^0.6.0"
3223+
31863224
source-map-support@~0.5.12:
31873225
version "0.5.13"
31883226
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932"
@@ -3477,20 +3515,31 @@ trim-newlines@^1.0.0:
34773515
resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613"
34783516
integrity sha1-WIeWa7WCpFA6QetST301ARgVphM=
34793517

3518+
ts-node@~8.5.4:
3519+
version "8.5.4"
3520+
resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-8.5.4.tgz#a152add11fa19c221d0b48962c210cf467262ab2"
3521+
integrity sha512-izbVCRV68EasEPQ8MSIGBNK9dc/4sYJJKYA+IarMQct1RtEot6Xp0bXuClsbUSnKpg50ho+aOAx8en5c+y4OFw==
3522+
dependencies:
3523+
arg "^4.1.0"
3524+
diff "^4.0.1"
3525+
make-error "^1.1.1"
3526+
source-map-support "^0.5.6"
3527+
yn "^3.0.0"
3528+
34803529
[email protected], tslib@^1.8.0, tslib@^1.8.1:
34813530
version "1.10.0"
34823531
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a"
34833532
integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==
34843533

3485-
tslint-no-circular-imports@^0.7.0:
3534+
tslint-no-circular-imports@~0.7.0:
34863535
version "0.7.0"
34873536
resolved "https://registry.yarnpkg.com/tslint-no-circular-imports/-/tslint-no-circular-imports-0.7.0.tgz#9df0a15654d66b172e0b7843eed073fa5ae99b5f"
34883537
integrity sha512-k3wxpeMC4ef40UbpfBVHEHIzKfNZq5/SCtAO1YjGsaNTklo+K53/TWLrym+poA65RJFDiYgYNWvkeIIkJNA0Vw==
34893538

3490-
tslint@^5.20.0:
3491-
version "5.20.0"
3492-
resolved "https://registry.yarnpkg.com/tslint/-/tslint-5.20.0.tgz#fac93bfa79568a5a24e7be9cdde5e02b02d00ec1"
3493-
integrity sha512-2vqIvkMHbnx8acMogAERQ/IuINOq6DFqgF8/VDvhEkBqQh/x6SP0Y+OHnKth9/ZcHQSroOZwUQSN18v8KKF0/g==
3539+
tslint@~5.20.0:
3540+
version "5.20.1"
3541+
resolved "https://registry.yarnpkg.com/tslint/-/tslint-5.20.1.tgz#e401e8aeda0152bc44dd07e614034f3f80c67b7d"
3542+
integrity sha512-EcMxhzCFt8k+/UP5r8waCf/lzmeSyVlqxqMEDQE7rWYiQky8KpIBz1JAoYXfROHrPZ1XXd43q8yQnULOLiBRQg==
34943543
dependencies:
34953544
"@babel/code-frame" "^7.0.0"
34963545
builtin-modules "^1.1.1"
@@ -3799,3 +3848,8 @@ [email protected]:
37993848
version "0.1.2"
38003849
resolved "https://registry.yarnpkg.com/yeast/-/yeast-0.1.2.tgz#008e06d8094320c372dbc2f8ed76a0ca6c8ac419"
38013850
integrity sha1-AI4G2AlDIMNy28L47XagymyKxBk=
3851+
3852+
yn@^3.0.0:
3853+
version "3.1.1"
3854+
resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50"
3855+
integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==

tfjs-core/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
"devDependencies": {
2222
"@bazel/bazel": "^0.24.0",
2323
"@bazel/typescript": "^0.27.8",
24-
"@types/jasmine": "~2.5.53",
24+
"@types/jasmine": "~3.0.0",
2525
"@types/node": "~9.6.0",
2626
"@types/node-fetch": "~2.1.2",
2727
"browserify": "~16.2.3",

tfjs-core/src/backends/cpu/backend_cpu.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ export class MathBackendCPU extends KernelBackend {
103103
'Then call require(\'@tensorflow/tfjs-node\'); (-gpu ' +
104104
'suffix for CUDA) at the start of your program. ' +
105105
'Visit https://github.com/tensorflow/tfjs-node for more details.' +
106-
'\n============================\n');
106+
'\n============================');
107107
}
108108
}
109109
const dataId = {};

tfjs-core/src/backends/cpu/backend_cpu_test.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ describeWithFlags('memory cpu', CPU_ENVS, () => {
135135
});
136136
});
137137

138-
describeWithFlags('CPU backend has sync init', {}, () => {
138+
describeWithFlags('CPU backend has sync init', CPU_ENVS, () => {
139139
it('can do matmul without waiting for ready', async () => {
140140
tf.registerBackend('my-cpu', () => {
141141
return new MathBackendCPU();
@@ -149,3 +149,19 @@ describeWithFlags('CPU backend has sync init', {}, () => {
149149
tf.removeBackend('my-cpu');
150150
});
151151
});
152+
153+
// NOTE: This describe is purposefully not a describeWithFlags so that we
154+
// test tensor allocation where no scopes have been created. The backend
155+
// here must be set to CPU because we cannot allocate GPU tensors outside
156+
// a describeWithFlags because the default webgl backend and the test
157+
// backends share a WebGLContext. When backends get registered, global
158+
// WebGL state is initialized, which causes the two backends to step on
159+
// each other and get in a bad state.
160+
describe('Memory allocation outside a test scope', () => {
161+
it('constructing a tensor works', async () => {
162+
tf.setBackend('cpu');
163+
const a = tf.tensor1d([1, 2, 3]);
164+
expectArraysClose(await a.data(), [1, 2, 3]);
165+
a.dispose();
166+
});
167+
});

0 commit comments

Comments
 (0)