File tree Expand file tree Collapse file tree 3 files changed +53
-3
lines changed Expand file tree Collapse file tree 3 files changed +53
-3
lines changed Original file line number Diff line number Diff line change
1
+ import LazyScratchBlocks from './tw-lazy-scratch-blocks' ;
2
+
3
+ /**
4
+ * Implements Scratch.gui API for unsandboxed extensions.
5
+ * @param {any } Scratch window.Scratch, mutated in place.
6
+ */
7
+ const implementGuiAPI = Scratch => {
8
+ Scratch . gui = {
9
+ /**
10
+ * Lazily get the internal ScratchBlocks object when it becomes available. It may never be
11
+ * available if, for example, the user never enters the editor.
12
+ *
13
+ * ScratchBlocks becoming available does not necessarily mean the user is in the editor due
14
+ * to getBlocklyEagerly() also existing.
15
+ *
16
+ * @returns {Promise<any> } Promise that may eventually resolve to ScratchBlocks
17
+ */
18
+ getBlockly : ( ) => new Promise ( resolve => LazyScratchBlocks . onLoaded ( resolve ) ) ,
19
+
20
+ /**
21
+ * Get the internal ScratchBlocks object as soon as possible. This lets you access it even
22
+ * if the user never enters the editor.
23
+ *
24
+ * This method is VERY SLOW and will cause A LOT OF CPU AND NETWORK ACTIVITY because it
25
+ * downloads and evaluates all of scratch-blocks, a multi-megabyte JavaScript bundle.
26
+ *
27
+ * @returns {Promise<any> } Promise that will resolve to ScratchBlocks.
28
+ */
29
+ getBlocklyEagerly : ( ) => LazyScratchBlocks . load ( )
30
+ } ;
31
+ } ;
32
+
33
+ export default implementGuiAPI ;
Original file line number Diff line number Diff line change @@ -15,24 +15,30 @@ const wasNameYourmom = () => {
15
15
return old ;
16
16
} ;
17
17
18
+ const callbacks = [ ] ;
18
19
const isLoaded = ( ) => ! ! _ScratchBlocks && ( isNameUrMom ( ) === wasNameYourmom ( ) ) ;
19
20
20
21
const get = ( ) => {
21
- if ( ! isLoaded ( ) ) {
22
+ if ( ! _ScratchBlocks ) {
22
23
throw new Error ( 'scratch-blocks is not loaded yet' ) ;
23
24
}
24
25
return _ScratchBlocks ;
25
26
} ;
26
27
27
28
const load = ( ) => {
28
29
if ( _ScratchBlocks && ( isNameUrMom ( ) === wasNameYourmom ( ) ) ) {
29
- return Promise . resolve ( ) ;
30
+ return Promise . resolve ( _ScratchBlocks ) ;
30
31
}
31
32
_ScratchBlocks = null ;
32
33
return import ( /* webpackChunkName: "sb" */ 'scratch-blocks' )
33
34
. then ( m => {
34
35
_ScratchBlocks = m . default ;
35
36
37
+ for ( const callback of callbacks ) {
38
+ callback ( _ScratchBlocks ) ;
39
+ }
40
+ callbacks . length = 0 ;
41
+
36
42
if ( isNameUrMom ( ) ) {
37
43
_ScratchBlocks . Blocks . your_mom = {
38
44
init ( ) {
@@ -134,10 +140,19 @@ const load = () => {
134
140
} ) ;
135
141
} ;
136
142
143
+ const onLoaded = callback => {
144
+ if ( _ScratchBlocks ) {
145
+ callback ( _ScratchBlocks ) ;
146
+ } else {
147
+ callbacks . push ( callback ) ;
148
+ }
149
+ } ;
150
+
137
151
export default {
138
152
get,
139
153
isLoaded,
140
154
isNameUrMom,
141
155
wasNameYourmom,
142
- load
156
+ load,
157
+ onLoaded
143
158
} ;
Original file line number Diff line number Diff line change @@ -22,6 +22,7 @@ import {
22
22
setHasCloudVariables
23
23
} from '../reducers/tw' ;
24
24
import { setCustomStageSize } from '../reducers/custom-stage-size' ;
25
+ import implementGuiAPI from './tw-extension-gui-api' ;
25
26
26
27
let compileErrorCounter = 0 ;
27
28
@@ -73,6 +74,7 @@ const vmListenerHOC = function (WrappedComponent) {
73
74
this . props . vm . on ( 'COMPILE_ERROR' , this . handleCompileError ) ;
74
75
this . props . vm . on ( 'RUNTIME_STARTED' , this . props . onClearCompileErrors ) ;
75
76
this . props . vm . on ( 'STAGE_SIZE_CHANGED' , this . props . onStageSizeChanged ) ;
77
+ this . props . vm . on ( 'CREATE_UNSANDBOXED_EXTENSION_API' , implementGuiAPI ) ;
76
78
}
77
79
componentDidMount ( ) {
78
80
if ( this . props . attachKeyboardEvents ) {
You can’t perform that action at this time.
0 commit comments