Skip to content

Commit a691e34

Browse files
authored
Merge branch 'master' into java-slang-frontend
2 parents 399eebe + 94c6237 commit a691e34

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+2098
-1978
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ env:
1515
concurrency:
1616
group: ${{ github.workflow }}-${{ github.ref }}
1717
cancel-in-progress: true
18-
18+
1919
jobs:
2020
lint:
2121
if: github.event.pull_request.draft == false

CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ To start contributing, create a fork from our repo and send a PR. Refer to [this
1616

1717
The frontend comes with an extensive test suite. To run the tests after you made your modifications, run
1818
`yarn test`. Regression tests are run automatically when you want to push changes to this repository.
19-
The regression tests are generated using `jest` and stored as snapshots in `src/\_\_tests\_\_`. After modifying the frontend, carefully inspect any failing regression tests reported in red in the command line. If you are convinced that the regression tests and not your changes are at fault, you can update the regression tests by running:
19+
The regression tests are generated using `jest` and stored as snapshots in `src/\_\_tests\_\_`. After modifying the frontend, carefully inspect any failing regression tests reported in red in the command line. If you are convinced that the regression tests and not your changes are at fault, you can update the regression tests by running:
2020

2121
```bash
2222
yarn test --updateSnapshot

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ The Source Academy (<https://sourceacademy.org/>) is an immersive online experie
2424

2525
1. Clone this repository and navigate to it using your command line
2626

27-
1. Install the version of `yarn` as specified in `package.json`, `packageManager`.
27+
1. Install the version of `yarn` as specified in `package.json`, `packageManager`.
2828

2929
> We recommend using `corepack` to manage the version of `yarn`, you may simply run `corepack enable` to complete this step.
3030

_config.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
theme: jekyll-theme-cayman
1+
theme: jekyll-theme-cayman

eslint.config.mjs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import { config, configs } from 'typescript-eslint';
55
import reactPlugin from 'eslint-plugin-react';
66
import reactHooksPlugin from 'eslint-plugin-react-hooks';
7-
import simpleImportSort from 'eslint-plugin-simple-import-sort'
7+
import simpleImportSort from 'eslint-plugin-simple-import-sort';
88
// import reactRefresh from 'eslint-plugin-react-refresh';
99

1010
export default config(
@@ -24,7 +24,7 @@ export default config(
2424
files: ['**/*.ts*'],
2525
plugins: {
2626
'react-hooks': reactHooksPlugin,
27-
'react': reactPlugin,
27+
react: reactPlugin,
2828
'simple-import-sort': simpleImportSort
2929
},
3030
rules: {

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858
"i18next-browser-languagedetector": "^8.0.0",
5959
"java-slang": "^1.0.13",
6060
"js-cookie": "^3.0.5",
61-
"js-slang": "^1.0.81",
61+
"js-slang": "^1.0.82",
6262
"js-yaml": "^4.1.0",
6363
"konva": "^9.2.0",
6464
"language-directory": "https://github.com/source-academy/language-directory.git",

public/externalLibs/sound/soundToneMatrix.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ var timeout_matrix;
3636
// for coloring the matrix accordingly while it's being played
3737
var timeout_color;
3838

39-
var timeout_objects = new Array();
39+
var timeout_objects = [];
4040

4141
// vector_to_list returns a list that contains the elements of the argument vector
4242
// in the given order.
@@ -54,7 +54,7 @@ function vector_to_list(vector) {
5454
function x_y_to_row_column(x, y) {
5555
var row = Math.floor((y - margin_length) / (square_side_length + distance_between_squares));
5656
var column = Math.floor((x - margin_length) / (square_side_length + distance_between_squares));
57-
return Array(row, column);
57+
return [row, column];
5858
}
5959

6060
// given the row number of a square, return the leftmost coordinate
@@ -365,5 +365,5 @@ function clear_all_timeout() {
365365
clearTimeout(timeout_objects[i]);
366366
}
367367

368-
timeout_objects = new Array();
368+
timeout_objects = [];
369369
}

public/manifest.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,16 @@
1313
"type": "image/png"
1414
},
1515
{
16-
"src": "icons/android-chrome-256x256.png",
17-
"sizes": "256x256",
18-
"type": "image/png"
16+
"src": "icons/android-chrome-256x256.png",
17+
"sizes": "256x256",
18+
"type": "image/png"
1919
},
2020
{
2121
"src": "icons/maskable.png",
2222
"sizes": "196x196",
2323
"type": "image/png",
2424
"purpose": "maskable"
25-
}
25+
}
2626
],
2727
"start_url": "./",
2828
"display": "standalone",

src/commons/__tests__/Markdown.tsx

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,6 @@ test('Markdown page renders correct Source information', () => {
3131
const source3Default = <Markdown {...mockProps(Chapter.SOURCE_3, Variant.DEFAULT)} />;
3232
expect(source3Default.props.content).toContain('Source \xa73');
3333

34-
const source3Concurrent = <Markdown {...mockProps(Chapter.SOURCE_3, Variant.CONCURRENT)} />;
35-
expect(source3Concurrent.props.content).toContain('Source \xa73 Concurrent');
36-
3734
const source4Default = <Markdown {...mockProps(Chapter.SOURCE_4, Variant.DEFAULT)} />;
3835
expect(source4Default.props.content).toContain('Source \xa74');
3936
});

src/commons/application/ApplicationTypes.ts

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,27 @@
1-
import { Chapter, Language, SourceError, Variant } from 'js-slang/dist/types';
1+
import { Chapter, Language, type SourceError, type Value, Variant } from 'js-slang/dist/types';
22

3-
import { AchievementState } from '../../features/achievement/AchievementTypes';
4-
import { DashboardState } from '../../features/dashboard/DashboardTypes';
5-
import { PlaygroundState } from '../../features/playground/PlaygroundTypes';
3+
import type { AchievementState } from '../../features/achievement/AchievementTypes';
4+
import type { DashboardState } from '../../features/dashboard/DashboardTypes';
5+
import type { PlaygroundState } from '../../features/playground/PlaygroundTypes';
66
import { PlaybackStatus, RecordingStatus } from '../../features/sourceRecorder/SourceRecorderTypes';
7-
import { StoriesEnvState, StoriesState } from '../../features/stories/StoriesTypes';
7+
import type { StoriesEnvState, StoriesState } from '../../features/stories/StoriesTypes';
88
import { freshSortState } from '../../pages/academy/grading/subcomponents/GradingSubmissionsTable';
99
import { WORKSPACE_BASE_PATHS } from '../../pages/fileSystem/createInBrowserFileSystem';
1010
import { defaultFeatureFlags, FeatureFlagsState } from '../featureFlags';
11-
import { FileSystemState } from '../fileSystem/FileSystemTypes';
12-
import { SideContentManagerState, SideContentState } from '../sideContent/SideContentTypes';
11+
import type { FileSystemState } from '../fileSystem/FileSystemTypes';
12+
import type { SideContentManagerState, SideContentState } from '../sideContent/SideContentTypes';
1313
import Constants from '../utils/Constants';
1414
import { createContext } from '../utils/JsSlangHelper';
15-
import {
15+
import type {
1616
DebuggerContext,
1717
WorkspaceLocation,
1818
WorkspaceManagerState,
1919
WorkspaceState
2020
} from '../workspace/WorkspaceTypes';
21-
import { RouterState } from './types/CommonsTypes';
21+
import type { RouterState } from './types/CommonsTypes';
2222
import { ExternalLibraryName } from './types/ExternalTypes';
23-
import { SessionState } from './types/SessionTypes';
24-
import { VscodeState as VscodeState } from './types/VscodeTypes';
23+
import type { SessionState } from './types/SessionTypes';
24+
import type { VscodeState as VscodeState } from './types/VscodeTypes';
2525

2626
export type OverallState = {
2727
readonly router: RouterState;
@@ -74,7 +74,7 @@ export type CodeOutput = {
7474
*/
7575
export type ResultOutput = {
7676
type: 'result';
77-
value: any;
77+
value: Value;
7878
consoleLogs: string[];
7979
runtime?: number;
8080
isProgram?: boolean;
@@ -160,7 +160,6 @@ type LanguageFeatures = Partial<{
160160
const variantDisplay: Map<Variant, string> = new Map([
161161
[Variant.TYPED, 'Typed'],
162162
[Variant.WASM, 'WebAssembly'],
163-
[Variant.CONCURRENT, 'Concurrent'],
164163
[Variant.NATIVE, 'Native'],
165164
[Variant.EXPLICIT_CONTROL, 'Explicit-Control']
166165
]);
@@ -266,7 +265,6 @@ const sourceSubLanguages: Array<Pick<SALanguage, 'chapter' | 'variant'>> = [
266265

267266
{ chapter: Chapter.SOURCE_3, variant: Variant.DEFAULT },
268267
{ chapter: Chapter.SOURCE_3, variant: Variant.TYPED },
269-
{ chapter: Chapter.SOURCE_3, variant: Variant.CONCURRENT },
270268
{ chapter: Chapter.SOURCE_3, variant: Variant.NATIVE },
271269

272270
{ chapter: Chapter.SOURCE_4, variant: Variant.DEFAULT },
@@ -288,13 +286,13 @@ export const sourceLanguages: SALanguage[] = sourceSubLanguages.map(sublang => {
288286
(variant === Variant.DEFAULT || variant === Variant.NATIVE || variant === Variant.TYPED);
289287

290288
// Enable CSE Machine for Source Chapter 3 and above
291-
supportedFeatures.cseMachine = chapter >= Chapter.SOURCE_3 && variant !== Variant.CONCURRENT;
289+
supportedFeatures.cseMachine = chapter >= Chapter.SOURCE_3;
292290

293291
// Local imports/exports require Source 2+ as Source 1 does not have lists.
294292
supportedFeatures.multiFile = chapter >= Chapter.SOURCE_2;
295293

296294
// Disable REPL for concurrent variants
297-
supportedFeatures.repl = variant !== Variant.CONCURRENT;
295+
supportedFeatures.repl = true;
298296

299297
return {
300298
...sublang,

src/commons/application/__tests__/ApplicationTypes.ts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,6 @@ describe('available Source language configurations', () => {
5555
variant: Variant.TYPED,
5656
supports: { dataVisualizer: true, cseMachine: true }
5757
},
58-
{
59-
chapter: Chapter.SOURCE_3,
60-
variant: Variant.CONCURRENT,
61-
supports: { dataVisualizer: true }
62-
},
6358
{
6459
chapter: Chapter.SOURCE_3,
6560
variant: Variant.NATIVE,

src/commons/application/__tests__/__snapshots__/ApplicationTypes.ts.snap

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -188,19 +188,6 @@ Array [
188188
},
189189
"variant": "typed",
190190
},
191-
Object {
192-
"chapter": 3,
193-
"displayName": "Source §3 Concurrent",
194-
"mainLanguage": "JavaScript",
195-
"supports": Object {
196-
"cseMachine": false,
197-
"dataVisualizer": true,
198-
"multiFile": true,
199-
"repl": false,
200-
"substVisualizer": false,
201-
},
202-
"variant": "concurrent",
203-
},
204191
Object {
205192
"chapter": 3,
206193
"displayName": "Source §3 Native",

src/commons/application/actions/SessionActions.ts

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,27 +4,27 @@ import {
44
unpublishedToBackendParams
55
} from 'src/features/grading/GradingUtils';
66
import { freshSortState } from 'src/pages/academy/grading/subcomponents/GradingSubmissionsTable';
7-
import { OptionType } from 'src/pages/academy/teamFormation/subcomponents/TeamFormationForm';
7+
import type { OptionType } from 'src/pages/academy/teamFormation/subcomponents/TeamFormationForm';
88

9-
import {
9+
import type {
1010
AllColsSortStates,
1111
GradingOverviews,
1212
GradingQuery
1313
} from '../../../features/grading/GradingTypes';
14-
import { TeamFormationOverview } from '../../../features/teamFormation/TeamFormationTypes';
15-
import {
14+
import type { TeamFormationOverview } from '../../../features/teamFormation/TeamFormationTypes';
15+
import type {
1616
Assessment,
1717
AssessmentConfiguration,
1818
AssessmentOverview,
1919
ContestEntry
2020
} from '../../assessment/AssessmentTypes';
21-
import {
21+
import type {
2222
Notification,
2323
NotificationFilterFunction
2424
} from '../../notificationBadge/NotificationBadgeTypes';
2525
import { generateOctokitInstance } from '../../utils/GitHubPersistenceHelper';
2626
import { Role, StoriesRole } from '../ApplicationTypes';
27-
import {
27+
import type {
2828
AdminPanelCourseRegistration,
2929
CourseRegistration,
3030
Tokens,
@@ -153,6 +153,4 @@ const SessionActions = createActions('session', {
153153
});
154154

155155
// For compatibility with existing code (actions helper)
156-
export default {
157-
...SessionActions
158-
};
156+
export default SessionActions;

src/commons/mocks/ContextMocks.ts

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
import { parse } from 'acorn';
2-
import { FunctionExpression, Node } from 'estree';
2+
import type { Node } from 'estree';
33
import { ACORN_PARSE_OPTIONS } from 'js-slang/dist/constants';
44
import createContext, { EnvTree } from 'js-slang/dist/createContext';
5-
import Closure from 'js-slang/dist/interpreter/closure';
6-
import { Context, Environment } from 'js-slang/dist/types';
5+
import type { Context } from 'js-slang/dist/types';
76
import { TypeError } from 'js-slang/dist/utils/rttc';
87

98
export function mockContext(chapter = 1): Context {
@@ -44,10 +43,6 @@ export function mockRuntimeContext(): Context {
4443
return context;
4544
}
4645

47-
export function mockClosure(): Closure {
48-
return new Closure({} as FunctionExpression, {} as Environment, {} as Context);
49-
}
50-
5146
export function mockTypeError(): TypeError {
5247
// Typecast to Node to fix estree-acorn compatability.
5348
return new TypeError(parse('', ACORN_PARSE_OPTIONS) as Node, '', '', '');

src/commons/redux/__tests__/utils.ts

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import { testSaga } from 'redux-saga-test-plan';
2+
import WorkspaceActions from 'src/commons/workspace/WorkspaceActions';
3+
4+
import { combineSagaHandlers, createActions } from '../utils';
5+
6+
// Would have used spyOn, but for some reason that doesn't work properly
7+
jest.mock('src/commons/sagas/SafeEffects', () => ({
8+
...jest.requireActual('src/commons/sagas/SafeEffects'),
9+
// Mock wrap saga to just be a passthrough so that the identity
10+
// checking that testSaga uses will pass
11+
wrapSaga: (x: any) => x
12+
}));
13+
14+
test('test combineSagaHandlers', () => {
15+
const mockTakeEveryHandler = jest.fn();
16+
const mockTakeLatestHandler = jest.fn();
17+
const mockTakeLeadingHandler = jest.fn();
18+
19+
const saga = combineSagaHandlers({
20+
[WorkspaceActions.toggleUsingUpload.type]: mockTakeEveryHandler,
21+
[WorkspaceActions.toggleFolderMode.type]: {
22+
takeEvery: mockTakeEveryHandler
23+
},
24+
[WorkspaceActions.toggleUsingCse.type]: {
25+
takeLatest: mockTakeLatestHandler
26+
},
27+
[WorkspaceActions.toggleUsingSubst.type]: {
28+
takeLeading: mockTakeLeadingHandler
29+
},
30+
[WorkspaceActions.toggleEditorAutorun.type]: {
31+
takeEvery: mockTakeEveryHandler,
32+
takeLeading: mockTakeLeadingHandler
33+
}
34+
});
35+
36+
testSaga(saga)
37+
.next()
38+
.takeEvery(WorkspaceActions.toggleUsingUpload.type, mockTakeEveryHandler)
39+
.next()
40+
.takeEvery(WorkspaceActions.toggleFolderMode.type, mockTakeEveryHandler)
41+
.next()
42+
.takeLatest(WorkspaceActions.toggleUsingCse.type, mockTakeLatestHandler)
43+
.next()
44+
.takeLeading(WorkspaceActions.toggleUsingSubst.type, mockTakeLeadingHandler)
45+
.next()
46+
.takeEvery(WorkspaceActions.toggleEditorAutorun.type, mockTakeEveryHandler)
47+
.next()
48+
.takeLeading(WorkspaceActions.toggleEditorAutorun.type, mockTakeLeadingHandler)
49+
.next()
50+
.isDone();
51+
});
52+
53+
test('createActions', () => {
54+
const actions = createActions('workspace', {
55+
act0: false,
56+
act1: (value: string) => ({ value }),
57+
act2: 525600
58+
});
59+
60+
const act0 = actions.act0();
61+
expect(act0.type).toEqual('workspace/act0');
62+
63+
const act1 = actions.act1('test');
64+
expect(act1.type).toEqual('workspace/act1');
65+
expect(act1.payload).toMatchObject({ value: 'test' });
66+
67+
const act2 = actions.act2();
68+
expect(act2.type).toEqual('workspace/act2');
69+
});

0 commit comments

Comments
 (0)