Skip to content

Commit

Permalink
Merge branch 'main' into select-placeholder
Browse files Browse the repository at this point in the history
  • Loading branch information
atmgrifter00 authored Feb 28, 2024
2 parents aedd65e + 5269352 commit cce5ae7
Show file tree
Hide file tree
Showing 15 changed files with 221 additions and 1 deletion.
1 change: 1 addition & 0 deletions .github/renovate.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"^@tanstack/",
"^@tiptap/",
"@types/markdown-it",
"comlink",
"d3-",
"prosemirror-"
],
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "patch",
"comment": "Create web worker class for future faster rendering wafer map",
"packageName": "@ni/nimble-components",
"email": "[email protected]",
"dependentChangeType": "patch"
}
6 changes: 6 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions packages/nimble-components/.gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
src/icons
src/wafer-map/workers
1 change: 1 addition & 0 deletions packages/nimble-components/.prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,4 @@ src/utilities/tests/fixture.ts
src/utilities/style/direction.ts
src/icons/**/*.ts
build/transform-fragments.js
src/wafer-map/workers
18 changes: 18 additions & 0 deletions packages/nimble-components/build/generate-workers/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generate Workers

This directory contains wafer map rendering code and build scripts which compile it to run in a web worker.

## Behavior

- the `source` directory and `index.ts` are built using `tsc`
- `source/matrix-renderer.ts` is bundled with rollup
- `index.ts` has the purpose to prepare and move `dist/bundle/matrix-renderer` to `src/wafer-map/worker`
- `src/wafer-map/worker/matrix-renderer` will be used to create a `Blob` object which is then used to create a `URL` for a web worker.

## How to run

This script runs as part of `npm run build` but before `npm run build-components`.

To run manually:

1. Run `npm run generate-workers` inside nimble-components directory.
39 changes: 39 additions & 0 deletions packages/nimble-components/build/generate-workers/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
const fs = require('fs');
const path = require('path');

function resolveModulePath(moduleName: string): string {
return path.resolve(require.resolve(moduleName));
}

function prepareDirectory(dirPath: string): void {
if (fs.existsSync(dirPath)) {
console.log(`Deleting existing directory "${dirPath}"`);
fs.rmSync(dirPath, { recursive: true });
console.log('Finished deleting existing directory');
}
console.log(`Creating directory "${dirPath}"`);
fs.mkdirSync(dirPath);
console.log('Finished creating directory');
}

function writeFile(filePath: string, content: string): void {
console.log(`Writing file "${filePath}"`);
fs.writeFileSync(filePath, content, { encoding: 'utf-8' });
console.log('Finished writing file');
}

const renderModuleName: string = '../bundle/matrix-renderer.js';
const workersDirectory: string = path.resolve('./src/wafer-map/workers');

prepareDirectory(workersDirectory);

const modulePath: string = resolveModulePath(renderModuleName);
const sourceCode: string = fs.readFileSync(modulePath, 'utf-8');

const fileContent: string = `// eslint-disable-next-line no-template-curly-in-string
export const workerCode = ${JSON.stringify(sourceCode)};
`;

const renderFilePath: string = path.resolve(workersDirectory, 'matrix-renderer.ts');

writeFile(renderFilePath, fileContent);
13 changes: 13 additions & 0 deletions packages/nimble-components/build/generate-workers/rollup.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import nodeResolve from '@rollup/plugin-node-resolve';
import path from 'path';

export default {
input: path.resolve(__dirname, 'dist/esm/source/matrix-renderer.js'),
output: {
file: path.resolve(__dirname, 'dist/bundle/matrix-renderer.js'),
format: 'iife',
name: 'MatrixRenderer',
sourcemap: false
},
plugins: [nodeResolve()]
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { expose } from 'comlink';

/**
* MatrixRenderer class is meant to be used within a Web Worker context,
* using Comlink to facilitate communication between the main thread and the worker.
* The MatrixRenderer class manages a matrix of dies, once an instance of MatrixRenderer is created,
* it is exposed to the main thread using Comlink's `expose` method.
* This setup is used in the wafer-map component to perform heavy computational duties
*/
export class MatrixRenderer {
public dieMatrix: Uint8Array = Uint8Array.from([]);

public emptyMatrix(): void {
this.dieMatrix = Uint8Array.from([]);;
}

public updateMatrix(
data: Iterable<number>
): void {
this.dieMatrix = Uint8Array.from(data);
}
}
expose(MatrixRenderer);
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { Remote, expose, wrap } from 'comlink';
import { MatrixRenderer } from '../matrix-renderer';

describe('MatrixRenderer with MessageChannel', () => {
let matrixRenderer: Remote<MatrixRenderer>;

beforeEach(async () => {
const { port1, port2 } = new MessageChannel();
const worker = new MatrixRenderer();
expose(worker, port1);
matrixRenderer = await wrap<MatrixRenderer>(port2);
});

it('updateMatrix should update the dieMatrix', async () => {
const testData = [4, 5, 6];
await matrixRenderer.updateMatrix(testData);

const updatedMatrix = await matrixRenderer.dieMatrix;
expect(updatedMatrix).toEqual(Uint8Array.from(testData));
});

it('emptyMatrix should empty the dieMatrix', async () => {
await matrixRenderer.emptyMatrix();

const updatedMatrix = await matrixRenderer.dieMatrix;
expect(updatedMatrix.length).toEqual(0);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"extends": "../../tsconfig.json",
"include": ["source", "index.ts"],
"compilerOptions": {
"outDir": "./dist/esm"
}
}
7 changes: 6 additions & 1 deletion packages/nimble-components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"version": "21.7.0",
"description": "Styled web components for the NI Nimble Design System",
"scripts": {
"build": "npm run generate-icons && npm run build-components && npm run bundle-components && npm run generate-scss && npm run build-storybook",
"build": "npm run generate-icons && npm run generate-workers && npm run build-components && npm run bundle-components && npm run generate-scss && npm run build-storybook",
"lint": "npm run eslint && npm run prettier",
"format": "npm run eslint-fix && npm run prettier-fix",
"eslint": "eslint .",
Expand All @@ -24,6 +24,10 @@
"generate-scss": "npm run generate-scss:bundle && npm run generate-scss:run",
"generate-scss:bundle": "rollup --bundleConfigAsCjs --config build/generate-scss/rollup.config.js",
"generate-scss:run": "node build/generate-scss/dist/index.js",
"generate-workers": "npm run generate-workers:build && npm run generate-workers:bundle && npm run generate-workers:run",
"generate-workers:build": "tsc -p build/generate-workers/tsconfig.json",
"generate-workers:bundle": "rollup --bundleConfigAsCjs --config build/generate-workers/rollup.config.js",
"generate-workers:run": "node build/generate-workers/dist/esm/index.js",
"tdd": "npm run build-components && npm run test-chrome",
"tdd:watch": "npm run build-components:watch & npm run test-chrome:watch",
"tdd-firefox": "npm run build-components && npm run test-firefox",
Expand Down Expand Up @@ -87,6 +91,7 @@
"@types/d3-selection": "^3.0.0",
"@types/d3-zoom": "^3.0.0",
"@types/markdown-it": "^13.0.0",
"comlink": "4.4.1",
"d3-array": "^3.2.2",
"d3-random": "^3.0.1",
"d3-scale": "^4.0.2",
Expand Down
7 changes: 7 additions & 0 deletions packages/nimble-components/src/utilities/tests/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,10 @@ require('./setup-configuration.js');

// all browser test scripts
importAll(require.context('../../', true, /\.spec\.js$/));
importAll(
require.context(
'../../../../build/generate-workers/dist/esm',
true,
/\.spec\.js$/
)
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { wrap, Remote } from 'comlink';
import { workerCode } from '../workers/matrix-renderer';
import type { MatrixRenderer } from '../../../build/generate-workers/dist/esm/source/matrix-renderer';

let url: string;

/**
* Asynchronously creates and returns a Remote<MatrixRenderer> instance.
* This function simplifies the process of creating and accessing MatrixRenderer instances.
*/
export const createMatrixRenderer = async (): Promise<{
matrixRenderer: Remote<MatrixRenderer>,
terminate: () => void
}> => {
if (url === undefined) {
const blob = new Blob([workerCode], { type: 'text/javascript' });
url = URL.createObjectURL(blob);
}
const worker = new Worker(url);
// eslint-disable-next-line @typescript-eslint/naming-convention
const RemoteMatrixRenderer = wrap<new() => MatrixRenderer>(worker);
const matrixRenderer = await new RemoteMatrixRenderer();
const terminate = (): void => worker.terminate();
return {
matrixRenderer,
terminate
};
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import type { Remote } from 'comlink';
import { createMatrixRenderer } from '../modules/create-matrix-renderer';
import type { MatrixRenderer } from '../../../build/generate-workers/dist/esm/source/matrix-renderer';

describe('MatrixRenderer worker', () => {
let matrixRenderer: Remote<MatrixRenderer>;
let terminate: () => void;

beforeEach(async () => {
const result = await createMatrixRenderer();
matrixRenderer = result.matrixRenderer;
terminate = result.terminate;
});

afterEach(() => {
terminate();
matrixRenderer = undefined!;
});

it('updateMatrix should update the dieMatrix', async () => {
const testData = [4, 5, 6];
await matrixRenderer.updateMatrix(testData);
const resolvedDieMatrix = await matrixRenderer.dieMatrix;
expect(Array.from(resolvedDieMatrix)).toEqual(
Array.from(Uint8Array.from(testData))
);
});

it('emptyMatrix should empty the dieMatrix', async () => {
const testData = [4, 5, 6];
await matrixRenderer.updateMatrix(testData);
await matrixRenderer.emptyMatrix();
const resolvedDieMatrix = await matrixRenderer.dieMatrix;
expect(resolvedDieMatrix.length).toEqual(0);
});
});

0 comments on commit cce5ae7

Please sign in to comment.