Skip to content

Commit

Permalink
Modernize build system
Browse files Browse the repository at this point in the history
Switch from create-react-app to vite (and a few plugins). This had some cascading
effects:
- We need to use module workers in dev mode, which in turn means that we need to
  use modules for the Emscripten output. This does mean that we can now treat
  the Emscripten output as real .js and .wasm files (instead of the fictional
  .jsz and .wasmz extensions), which simplifies MIME type handling. Requires
  picking up mihaip/macemu@49787f8 and
  mihaip/minivmac@81f5b31.
- We also needed to stop using importScripts for the non-SharedArrayBuffer
  worker communication mode. We instead use sychronous XHRs (that the service
  worker can still intercept, and can output more directly as JSON).
- We use our own ESLint config instead of getting it via create-react-app. I
  ended up with a slightly stricter config, so some tweaks were made (e.g. in
  how we use nullish coalescing and declare array types)

Other cleanups done as part of this:
- Separate out devDependencies from production ones.
- Emulator definitions were moved into emultor-*-emulators.ts files, since they
  were getting kind of long.

Fixes #155
  • Loading branch information
mihaip committed May 28, 2023
1 parent b45b86e commit b221259
Show file tree
Hide file tree
Showing 44 changed files with 9,461 additions and 36,569 deletions.
5 changes: 4 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ FROM ubuntu:22.04

RUN apt update && apt install -y \
python3 cmake git build-essential \
autoconf libsdl1.2-dev wget lzip
autoconf libsdl1.2-dev wget lzip curl

RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - && \
apt-get install -y nodejs

# Emscripten still does not release arm64 versions of their Docker images
# (https://github.com/emscripten-core/emsdk/issues/1206) so we need to install
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Common development tasks, all done via `npm run`:
Common deployment tasks (also done via `npm run`)

- `build`: Rebuild for either local use (in the `build/` directory) or for Cloudflare Worker use
- `preview`: Serve built assets locally using Vite's server (will be running at https://localhost:4127)
- `worker-dev`: Preview built assets in a local Cloudflare Worker (requires a separate `build` invocation, result will be running at http://localhost:3128)
- `worker-deploy`: Deploy built assets to the live version of the Cloudflare Worker (requires a separate `build` invocation)

Expand Down
7 changes: 4 additions & 3 deletions public/index.html → index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,22 @@
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="A classic Mac loaded with everything you'd want."
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<link rel="apple-touch-icon" href="/logo192.png" />
<link rel="manifest" href="/manifest.json" />
<title>Infinite Mac</title>
</head>
<body>
<noscript>Infinite Mac requires JavaScript.</noscript>
<div id="root"></div>
<div id="dialog-root"></div>
<script type="module" src="/src/index.tsx"></script>
</body>
</html>
2 changes: 1 addition & 1 deletion minivmac
Submodule minivmac updated 2 files
+2 −0 setup/WRBGCFLS.i
+48 −18 src/OSGLUESC.c
44,275 changes: 8,345 additions & 35,930 deletions package-lock.json

Large diffs are not rendered by default.

128 changes: 107 additions & 21 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,33 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@types/audioworklet": "^0.0.36",
"@types/emscripten": "^1.39.4",
"@types/file-saver": "^2.0.3",
"@types/react": "^17.0.0",
"@types/react-dom": "^17.0.0",
"clang-format": "^1.8.0",
"file-saver": "^2.0.5",
"husky": "^6.0.0",
"idb-keyval": "^6.0.3",
"jszip": "^3.7.0",
"lint-staged": "^11.0.0",
"prettier": "^2.3.1",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-scripts": "4.0.3",
"ringbuf.js": "^0.3.3",
"service-worker-loader": "^4.0.2",
"typescript": "^4.1.2",
"worker-loader": "^3.0.8",
"worklet-loader": "^2.0.0",
"typescript": "^4.1.2"
},
"devDependencies": {
"@types/audioworklet": "^0.0.46",
"@types/emscripten": "^1.39.6",
"@types/file-saver": "^2.0.5",
"@types/react": "^18.2.6",
"@types/react-dom": "^18.2.4",
"@typescript-eslint/eslint-plugin": "^5.59.5",
"@typescript-eslint/parser": "^5.59.5",
"@vitejs/plugin-basic-ssl": "^1.0.1",
"@vitejs/plugin-react": "^4.0.0",
"clang-format": "^1.8.0",
"eslint": "^8.40.0",
"eslint-plugin-import": "^2.27.5",
"eslint-plugin-react-hooks": "^4.6.0",
"husky": "^6.0.0",
"lint-staged": "^11.0.0",
"prettier": "^2.3.1",
"vite": "^4.3.5",
"vite-plugin-svgr": "^3.2.0",
"wrangler": "^2.14.0"
},
"scripts": {
Expand All @@ -31,28 +38,107 @@
"import-cd-roms": "scripts/import-cd-roms.py",
"load-placeholder-stickies-file": "scripts/load-placeholder-stickies-file.py",
"build-xadmaster": "scripts/build-xadmaster.sh",
"start": "PORT=3127 react-scripts start",
"build": "react-scripts build",
"eject": "react-scripts eject",
"start": "vite",
"build": "vite build",
"preview": "vite preview --host",
"worker-dev": "wrangler dev --local --port=3128",
"worker-deploy": "wrangler publish --env production",
"lint": "eslint src",
"check": "tsc --noEmit",
"format-macemu": "clang-format -i --glob=macemu/BasiliskII/src/Unix/JS/*"
},
"eslintConfig": {
"extends": [
"react-app"
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:react-hooks/recommended",
"plugin:import/recommended"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"project": true,
"tsconfigRootDir": "./"
},
"plugins": [
"@typescript-eslint"
],
"root": true,
"ignorePatterns": [
"src/emulator/minivmac-*.js",
"src/emulator/SheepShaver.js",
"src/emulator/BasiliskII.js"
],
"rules": {
"array-callback-return": "error",
"no-constant-binary-expression": "error",
"no-constructor-return": "error",
"no-promise-executor-return": "error",
"no-self-compare": "error",
"no-template-curly-in-string": "error",
"no-unmodified-loop-condition": "error",
"no-unreachable-loop": "error",
"require-atomic-updates": [
"error",
{
"allowProperties": true
}
],
"no-eval": "error",
"no-implied-eval": "error",
"no-new-object": "error",
"no-new-wrappers": "error",
"no-script-url": "error",
"no-useless-constructor": "error",
"no-useless-rename": "error",
"no-var": "error",
"eqeqeq": "error",
"object-shorthand": [
"error",
"always",
{
"avoidQuotes": true
}
],
"prefer-const": "error",
"import/no-webpack-loader-syntax": "off",
"no-restricted-globals": "off",
"import/no-unresolved": "off",
"@typescript-eslint/consistent-type-imports": [
"error",
{
"disallowTypeAnnotations": false
}
]
],
"@typescript-eslint/no-unused-vars": [
"error",
{
"vars": "all",
"args": "none",
"ignoreRestSiblings": false
}
],
"@typescript-eslint/prefer-optional-chain": "error",
"@typescript-eslint/array-type": "error",
"@typescript-eslint/consistent-generic-constructors": "error",
"@typescript-eslint/no-duplicate-enum-values": "error",
"@typescript-eslint/no-mixed-enums": "error",
"@typescript-eslint/no-unsafe-enum-comparison": "error",
"@typescript-eslint/no-dynamic-delete": "error",
"@typescript-eslint/prefer-nullish-coalescing": "error",
"@typescript-eslint/no-non-null-asserted-nullish-coalescing": "error",
"@typescript-eslint/no-unnecessary-type-arguments": "error",
"@typescript-eslint/non-nullable-type-assertion-style": "error",
"@typescript-eslint/prefer-for-of": "error",
"@typescript-eslint/prefer-includes": "error",
"@typescript-eslint/prefer-return-this-type": "error",
"@typescript-eslint/prefer-string-starts-ends-with": "error",
"@typescript-eslint/require-array-sort-compare": [
"error",
{
"ignoreStringArrays": true
}
],
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-inferrable-types": "off",
"@typescript-eslint/no-non-null-assertion": "off"
}
},
"browserslist": {
Expand Down
4 changes: 2 additions & 2 deletions scripts/import-emulator.sh
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ if [ ! -f "${EMULATOR_DIR}/${EMULATOR}.wasm" ]; then
fi

# Build output
cp "${EMULATOR_DIR}/${EMULATOR}" "${EMULATOR_DESTINATION_DIR}/${EMULATOR}.jsz"
cp "${EMULATOR_DIR}/${EMULATOR}.wasm" "${EMULATOR_DESTINATION_DIR}/${EMULATOR}.wasmz"
cp "${EMULATOR_DIR}/${EMULATOR}" "${EMULATOR_DESTINATION_DIR}/${EMULATOR}.js"
cp "${EMULATOR_DIR}/${EMULATOR}.wasm" "${EMULATOR_DESTINATION_DIR}/${EMULATOR}.wasm"
# Source map needs massaging and needs to be put into the public directory (we
# don't control the URL that it's referenced under).
scripts/rewrite-emulator-source-map.py "${EMULATOR_DIR}/${EMULATOR}.wasm.map" "${PUBLIC_DIR}/${EMULATOR}.wasm.map"
4 changes: 2 additions & 2 deletions src/Browser.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {useState} from "react";
import {Button} from "./Button";
import type {EmulatorEthernetProvider} from "./emulator/emulator-ui";
import {CloudflareWorkerEthernetProvider} from "./CloudflareWorkerEthernetProvider";
import {emulatorSupportsAppleTalk} from "./emulator/emulator-common";
import {emulatorSupportsAppleTalk} from "./emulator/emulator-common-emulators";
import {About} from "./About";
import {Donate} from "./Donate";
import {useWindowWidth} from "./useWindowWidth";
Expand Down Expand Up @@ -138,7 +138,7 @@ function DiskContents({disk, onRun, setBezelStyle}: DiskContentsProps) {
if (customizing) {
const appleTalkSupported =
disk.appleTalkSupported &&
emulatorSupportsAppleTalk(machine.emulator);
emulatorSupportsAppleTalk(machine.emulatorType);
contents = (
<>
<div className="Row">
Expand Down
3 changes: 2 additions & 1 deletion src/CloudflareWorkerEthernetProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,11 +127,12 @@ export class CloudflareWorkerEthernetProvider
const data = JSON.parse(event.data);
const {type} = data;
switch (type) {
case "receive":
case "receive": {
const {packetArray} = data;
const packet = new Uint8Array(packetArray);
this.#delegate?.receive(packet);
break;
}
}
};
}
18 changes: 10 additions & 8 deletions src/Mac.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,16 @@ import type {
EmulatorCDROM,
EmulatorCDROMLibrary,
EmulatorChunkedFileSpec,
} from "./emulator/emulator-common";
import {isDiskImageFile} from "./emulator/emulator-common";
import type {
EmulatorSpeed,
EmulatorType,
} from "./emulator/emulator-common";
} from "./emulator/emulator-common-emulators";
import {
emulatorSupportsSpeedSetting,
EMULATOR_SPEEDS,
isDiskImageFile,
} from "./emulator/emulator-common";
} from "./emulator/emulator-common-emulators";
import {useDevicePixelRatio} from "./useDevicePixelRatio";
import {usePersistentState} from "./usePersistentState";
import * as varz from "./varz";
Expand Down Expand Up @@ -59,7 +61,7 @@ export function Mac({
useState(false);
const [emulatorErrorText, setEmulatorErrorText] = useState("");
const [ethernetPeers, setEthernetPeers] = useState<
ReadonlyArray<EmulatorEthernetPeer>
readonly EmulatorEthernetPeer[]
>([]);
// Don't clear the loading state immediately, to make it clearer that I/O
// is happening and things may be slow.
Expand Down Expand Up @@ -168,7 +170,7 @@ export function Mac({
varz.incrementMulti({
"emulator_starts": 1,
"emulator_ethernet": ethernetProvider ? 1 : 0,
[`emulator_type:${machine.emulator}`]: 1,
[`emulator_type:${machine.emulatorType}`]: 1,
[`emulator_disk:${disk.name}`]: 1,
"emulator_shared_memory": useSharedMemory ? 1 : 0,
});
Expand Down Expand Up @@ -205,7 +207,7 @@ export function Mac({
};
const handleFullScreenChange = () => {
const isFullScreen = Boolean(
document.fullscreenElement || document.webkitFullscreenElement
document.fullscreenElement ?? document.webkitFullscreenElement
);
setFullscreen(isFullScreen);

Expand Down Expand Up @@ -421,7 +423,7 @@ export function Mac({
)}
{settingsVisible && (
<MacSettings
emulatorType={machine.emulator}
emulatorType={machine.emulatorType}
emulatorSettings={emulatorSettings}
buttonAppearance={
disk.hasPlatinumAppearance ? "Platinum" : "Classic"
Expand Down Expand Up @@ -477,7 +479,7 @@ function MacEthernetStatus({
peers,
}: {
provider: EmulatorEthernetProvider;
peers: ReadonlyArray<EmulatorEthernetPeer>;
peers: readonly EmulatorEthernetPeer[];
}) {
let text = `Ethernet: ${provider.description()}`;
const activePeerCount = peers.filter(
Expand Down
Loading

0 comments on commit b221259

Please sign in to comment.