@jsenv/core 23.6.1 → 23.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (135) hide show
  1. package/{license → LICENSE} +21 -21
  2. package/dist/jsenv_browser_system.js +35 -35
  3. package/dist/jsenv_browser_system.js.map +14 -14
  4. package/dist/jsenv_compile_proxy.js +47 -128
  5. package/dist/jsenv_compile_proxy.js.map +25 -62
  6. package/dist/jsenv_exploring_index.js.map +5 -5
  7. package/dist/jsenv_exploring_redirector.js +47 -54
  8. package/dist/jsenv_exploring_redirector.js.map +17 -19
  9. package/dist/jsenv_toolbar.js +47 -130
  10. package/dist/jsenv_toolbar.js.map +13 -48
  11. package/dist/jsenv_toolbar_injector.js.map +5 -5
  12. package/helpers/babel/.eslintrc.cjs +24 -24
  13. package/helpers/babel/AsyncGenerator/AsyncGenerator.js +81 -81
  14. package/helpers/babel/AwaitValue/AwaitValue.js +3 -3
  15. package/helpers/babel/applyDecoratorDescriptor/applyDecoratorDescriptor.js +33 -33
  16. package/helpers/babel/arrayLikeToArray/arrayLikeToArray.js +7 -7
  17. package/helpers/babel/arrayWithHoles/arrayWithHoles.js +4 -4
  18. package/helpers/babel/arrayWithoutHoles/arrayWithoutHoles.js +6 -6
  19. package/helpers/babel/assertThisInitialized/assertThisInitialized.js +7 -7
  20. package/helpers/babel/asyncGeneratorDelegate/asyncGeneratorDelegate.js +40 -40
  21. package/helpers/babel/asyncIterator/asyncIterator.js +12 -12
  22. package/helpers/babel/asyncToGenerator/asyncToGenerator.js +34 -34
  23. package/helpers/babel/awaitAsyncGenerator/awaitAsyncGenerator.js +5 -5
  24. package/helpers/babel/classApplyDescriptorDestructureSet/classApplyDescriptorDestructureSet.js +20 -20
  25. package/helpers/babel/classApplyDescriptorGet/classApplyDescriptorGet.js +6 -6
  26. package/helpers/babel/classApplyDescriptorSet/classApplyDescriptorSet.js +13 -13
  27. package/helpers/babel/classCallCheck/classCallCheck.js +5 -5
  28. package/helpers/babel/classCheckPrivateStaticAccess/classCheckPrivateStaticAccess.js +5 -5
  29. package/helpers/babel/classCheckPrivateStaticFieldDescriptor/classCheckPrivateStaticFieldDescriptor.js +6 -6
  30. package/helpers/babel/classExtractFieldDescriptor/classExtractFieldDescriptor.js +7 -7
  31. package/helpers/babel/classNameTDZError/classNameTDZError.js +4 -4
  32. package/helpers/babel/classPrivateFieldDestructureSet/classPrivateFieldDestructureSet.js +7 -7
  33. package/helpers/babel/classPrivateFieldGet/classPrivateFieldGet.js +7 -7
  34. package/helpers/babel/classPrivateFieldLooseBase/classPrivateFieldLooseBase.js +6 -6
  35. package/helpers/babel/classPrivateFieldLooseKey/classPrivateFieldLooseKey.js +5 -5
  36. package/helpers/babel/classPrivateFieldSet/classPrivateFieldSet.js +8 -8
  37. package/helpers/babel/classPrivateMethodGet/classPrivateMethodGet.js +6 -6
  38. package/helpers/babel/classPrivateMethodSet/classPrivateMethodSet.js +3 -3
  39. package/helpers/babel/classStaticPrivateFieldSpecGet/classStaticPrivateFieldSpecGet.js +9 -9
  40. package/helpers/babel/classStaticPrivateFieldSpecSet/classStaticPrivateFieldSpecSet.js +15 -15
  41. package/helpers/babel/classStaticPrivateMethodGet/classStaticPrivateMethodGet.js +6 -6
  42. package/helpers/babel/classStaticPrivateMethodSet/classStaticPrivateMethodSet.js +3 -3
  43. package/helpers/babel/construct/construct.js +16 -16
  44. package/helpers/babel/createClass/createClass.js +15 -15
  45. package/helpers/babel/createForOfIteratorHelper/createForOfIteratorHelper.js +60 -60
  46. package/helpers/babel/createForOfIteratorHelperLoose/createForOfIteratorHelperLoose.js +23 -23
  47. package/helpers/babel/createRawReactElement/createRawReactElement.js +50 -50
  48. package/helpers/babel/createSuper/createSuper.js +22 -22
  49. package/helpers/babel/decorate/decorate.js +403 -403
  50. package/helpers/babel/defaults/defaults.js +11 -11
  51. package/helpers/babel/defineEnumerableProperties/defineEnumerableProperties.js +23 -23
  52. package/helpers/babel/defineProperty/defineProperty.js +18 -18
  53. package/helpers/babel/extends/extends.js +14 -14
  54. package/helpers/babel/get/get.js +13 -13
  55. package/helpers/babel/getPrototypeOf/getPrototypeOf.js +4 -4
  56. package/helpers/babel/inherits/inherits.js +15 -15
  57. package/helpers/babel/inheritsLoose/inheritsLoose.js +7 -7
  58. package/helpers/babel/initializerDefineProperty/initializerDefineProperty.js +10 -10
  59. package/helpers/babel/initializerWarningHelper/initializerWarningHelper.js +6 -6
  60. package/helpers/babel/instanceof/instanceof.js +6 -6
  61. package/helpers/babel/interopRequireDefault/interopRequireDefault.js +3 -3
  62. package/helpers/babel/interopRequireWildcard/interopRequireWildcard.js +37 -37
  63. package/helpers/babel/isNativeFunction/isNativeFunction.js +4 -4
  64. package/helpers/babel/isNativeReflectConstruct/isNativeReflectConstruct.js +21 -21
  65. package/helpers/babel/iterableToArray/iterableToArray.js +7 -7
  66. package/helpers/babel/iterableToArrayLimit/iterableToArrayLimit.js +36 -36
  67. package/helpers/babel/iterableToArrayLimitLoose/iterableToArrayLimitLoose.js +10 -10
  68. package/helpers/babel/jsx/jsx.js +45 -45
  69. package/helpers/babel/maybeArrayLike/maybeArrayLike.js +10 -10
  70. package/helpers/babel/newArrowCheck/newArrowCheck.js +5 -5
  71. package/helpers/babel/nonIterableRest/nonIterableRest.js +5 -5
  72. package/helpers/babel/nonIterableSpread/nonIterableSpread.js +5 -5
  73. package/helpers/babel/objectDestructuringEmpty/objectDestructuringEmpty.js +3 -3
  74. package/helpers/babel/objectSpread/objectSpread.js +23 -23
  75. package/helpers/babel/objectSpread2/objectSpread2.js +33 -33
  76. package/helpers/babel/objectWithoutProperties/objectWithoutProperties.js +19 -19
  77. package/helpers/babel/objectWithoutPropertiesLoose/objectWithoutPropertiesLoose.js +13 -13
  78. package/helpers/babel/possibleConstructorReturn/possibleConstructorReturn.js +10 -10
  79. package/helpers/babel/readOnlyError/readOnlyError.js +4 -4
  80. package/helpers/babel/readme.md +9 -9
  81. package/helpers/babel/set/set.js +44 -44
  82. package/helpers/babel/setPrototypeOf/setPrototypeOf.js +6 -6
  83. package/helpers/babel/skipFirstGeneratorNext/skipFirstGeneratorNext.js +8 -8
  84. package/helpers/babel/slicedToArray/slicedToArray.js +10 -10
  85. package/helpers/babel/slicedToArrayLoose/slicedToArrayLoose.js +13 -13
  86. package/helpers/babel/superPropBase/superPropBase.js +10 -10
  87. package/helpers/babel/taggedTemplateLiteral/taggedTemplateLiteral.js +10 -10
  88. package/helpers/babel/taggedTemplateLiteralLoose/taggedTemplateLiteralLoose.js +7 -7
  89. package/helpers/babel/tdz/tdz.js +4 -4
  90. package/helpers/babel/temporalRef/temporalRef.js +6 -6
  91. package/helpers/babel/temporalUndefined/temporalUndefined.js +3 -3
  92. package/helpers/babel/toArray/toArray.js +10 -10
  93. package/helpers/babel/toConsumableArray/toConsumableArray.js +10 -10
  94. package/helpers/babel/toPrimitive/toPrimitive.js +10 -10
  95. package/helpers/babel/toPropertyKey/toPropertyKey.js +6 -6
  96. package/helpers/babel/typeof/typeof.js +14 -14
  97. package/helpers/babel/unsupportedIterableToArray/unsupportedIterableToArray.js +12 -12
  98. package/helpers/babel/wrapAsyncGenerator/wrapAsyncGenerator.js +8 -8
  99. package/helpers/babel/wrapNativeSuper/wrapNativeSuper.js +30 -30
  100. package/helpers/babel/wrapRegExp/wrapRegExp.js +63 -63
  101. package/helpers/babel/writeOnlyError/writeOnlyError.js +4 -4
  102. package/helpers/regenerator-runtime/regenerator-runtime.js +748 -748
  103. package/package.json +5 -3
  104. package/src/buildProject.js +300 -300
  105. package/src/execute.js +184 -184
  106. package/src/internal/browser-launcher/jsenv-browser-system.js +199 -199
  107. package/src/internal/compiling/babel_plugin_import_assertions.js +121 -100
  108. package/src/internal/compiling/babel_plugin_import_metadata.js +22 -0
  109. package/src/internal/compiling/babel_plugin_import_visitor.js +84 -0
  110. package/src/internal/compiling/compile-directory/getOrGenerateCompiledFile.js +268 -265
  111. package/src/internal/compiling/compile-directory/updateMeta.js +154 -150
  112. package/src/internal/compiling/compile-directory/validateCache.js +265 -265
  113. package/src/internal/compiling/compileFile.js +215 -200
  114. package/src/internal/compiling/compileHtml.js +550 -494
  115. package/src/internal/compiling/createCompiledFileService.js +291 -290
  116. package/src/internal/compiling/html_source_file_service.js +403 -379
  117. package/src/internal/compiling/js-compilation-service/jsenvTransform.js +270 -269
  118. package/src/internal/compiling/jsenvCompilerForHtml.js +300 -293
  119. package/src/internal/compiling/startCompileServer.js +1048 -1131
  120. package/src/internal/compiling/transformResultToCompilationResult.js +220 -217
  121. package/src/internal/executing/coverage/babel_plugin_instrument.js +90 -90
  122. package/src/internal/executing/coverage/reportToCoverage.js +187 -187
  123. package/src/internal/executing/executePlan.js +183 -183
  124. package/src/internal/executing/launchAndExecute.js +458 -450
  125. package/src/internal/runtime/createBrowserRuntime/scanBrowserRuntimeFeatures.js +246 -250
  126. package/src/internal/runtime/createNodeRuntime/scanNodeRuntimeFeatures.js +112 -115
  127. package/src/internal/runtime/s.js +727 -727
  128. package/src/internal/toolbar/jsenv-logo.svg +144 -144
  129. package/src/internal/toolbar/toolbar.main.css +196 -188
  130. package/src/internal/toolbar/toolbar.main.js +227 -228
  131. package/src/internal/url_conversion.js +317 -317
  132. package/src/startExploring.js +309 -309
  133. package/src/internal/compiling/babel_plugin_transform_import_specifier.js +0 -86
  134. package/src/internal/toolbar/animation/animation.css +0 -5
  135. package/src/internal/toolbar/variant/variant.css +0 -3
@@ -0,0 +1,84 @@
1
+ /*
2
+ * Not meant to be used directly
3
+ * Will be used either to put import specifier in metadata
4
+ * or to transform import specifiers
5
+ *
6
+ * see also
7
+ * https://github.com/jamiebuilds/babel-handbook/blob/master/translations/en/plugin-handbook.md
8
+ * https://github.com/mjackson/babel-plugin-import-visitor
9
+ *
10
+ */
11
+
12
+ export const babelPluginImportVisitor = (babel, importVisitor = () => {}) => {
13
+ return {
14
+ name: "import-visitor",
15
+
16
+ // manipulateOptions(opts, parserOpts) {
17
+ // parserOpts.plugins.push(
18
+ // "dynamicImport",
19
+ // "exportDefaultFrom",
20
+ // "exportNamespaceFrom",
21
+ // "importMeta",
22
+ // )
23
+ // },
24
+
25
+ visitor: {
26
+ CallExpression: (path, state) => {
27
+ if (path.node.callee.type !== "Import") {
28
+ // Some other function call, not import();
29
+ return
30
+ }
31
+
32
+ if (path.node.arguments[0].type !== "StringLiteral") {
33
+ // Non-string argument, probably a variable or expression, e.g.
34
+ // import(moduleId)
35
+ // import('./' + moduleName)
36
+ return
37
+ }
38
+
39
+ importVisitor({
40
+ importPath: path,
41
+ specifierPath: path.get("arguments")[0],
42
+ state,
43
+ babel,
44
+ })
45
+ },
46
+
47
+ ExportAllDeclaration: (path, state) => {
48
+ importVisitor({
49
+ importPath: path,
50
+ specifierPath: path.get("source"),
51
+ state,
52
+ babel,
53
+ })
54
+ },
55
+
56
+ ExportNamedDeclaration: (path, state) => {
57
+ if (!path.node.source) {
58
+ // This export has no "source", so it's probably
59
+ // a local variable or function, e.g.
60
+ // export { varName }
61
+ // export const constName = ...
62
+ // export function funcName() {}
63
+ return
64
+ }
65
+
66
+ importVisitor({
67
+ importPath: path,
68
+ specifierPath: path.get("source"),
69
+ state,
70
+ babel,
71
+ })
72
+ },
73
+
74
+ ImportDeclaration: (path, state) => {
75
+ importVisitor({
76
+ importPath: path,
77
+ specifierPath: path.get("source"),
78
+ state,
79
+ babel,
80
+ })
81
+ },
82
+ },
83
+ }
84
+ }
@@ -1,265 +1,268 @@
1
- import { urlToFileSystemPath } from "@jsenv/filesystem"
2
- import { createDetailedMessage } from "@jsenv/logger"
3
- import { timeStart, timeFunction } from "@jsenv/server"
4
- import { readFileContent } from "./fs-optimized-for-cache.js"
5
- import { validateCache } from "./validateCache.js"
6
- import { getMetaJsonFileUrl } from "./compile-asset.js"
7
- import { createLockRegistry } from "./createLockRegistry.js"
8
-
9
- const { lockForRessource } = createLockRegistry()
10
-
11
- export const getOrGenerateCompiledFile = async ({
12
- logger,
13
-
14
- projectDirectoryUrl,
15
- originalFileUrl,
16
- compiledFileUrl = originalFileUrl,
17
- compileCacheStrategy,
18
- compileCacheSourcesValidation,
19
- compileCacheAssetsValidation,
20
- fileContentFallback,
21
- request,
22
- compile,
23
- }) => {
24
- if (typeof projectDirectoryUrl !== "string") {
25
- throw new TypeError(
26
- `projectDirectoryUrl must be a string, got ${projectDirectoryUrl}`,
27
- )
28
- }
29
- if (typeof originalFileUrl !== "string") {
30
- throw new TypeError(
31
- `originalFileUrl must be a string, got ${originalFileUrl}`,
32
- )
33
- }
34
- if (!originalFileUrl.startsWith(projectDirectoryUrl)) {
35
- throw new Error(
36
- createDetailedMessage(`origin file must be inside project`, {
37
- ["original file url"]: originalFileUrl,
38
- ["project directory url"]: projectDirectoryUrl,
39
- }),
40
- )
41
- }
42
- if (typeof compiledFileUrl !== "string") {
43
- throw new TypeError(
44
- `compiledFileUrl must be a string, got ${compiledFileUrl}`,
45
- )
46
- }
47
- if (!compiledFileUrl.startsWith(projectDirectoryUrl)) {
48
- throw new Error(
49
- createDetailedMessage(`compiled file must be inside project`, {
50
- ["compiled file url"]: compiledFileUrl,
51
- ["project directory url"]: projectDirectoryUrl,
52
- }),
53
- )
54
- }
55
- if (typeof compile !== "function") {
56
- throw new TypeError(`compile must be a function, got ${compile}`)
57
- }
58
-
59
- const lockTimeEnd = timeStart("lock")
60
- return startAsap(
61
- async () => {
62
- const lockTiming = lockTimeEnd()
63
- const { meta, compileResult, compileResultStatus, timing } =
64
- await computeCompileReport({
65
- originalFileUrl,
66
- compiledFileUrl,
67
- compile,
68
- fileContentFallback,
69
- compileCacheStrategy,
70
- compileCacheSourcesValidation,
71
- compileCacheAssetsValidation,
72
- request,
73
- logger,
74
- })
75
-
76
- return {
77
- meta,
78
- compileResult,
79
- compileResultStatus,
80
- timing: {
81
- ...lockTiming,
82
- ...timing,
83
- },
84
- }
85
- },
86
- {
87
- compiledFileUrl,
88
- logger,
89
- },
90
- )
91
- }
92
-
93
- const computeCompileReport = async ({
94
- originalFileUrl,
95
- compiledFileUrl,
96
- compile,
97
- fileContentFallback,
98
- compileCacheStrategy,
99
- compileCacheSourcesValidation,
100
- compileCacheAssetsValidation,
101
- request,
102
- logger,
103
- }) => {
104
- const [readCacheTiming, cacheValidity] = await timeFunction(
105
- "read cache",
106
- () => {
107
- // if (!useFilesystemAsCache) {
108
- // return {
109
- // isValid: false,
110
- // code: "META_FILE_NOT_FOUND",
111
- // meta: {
112
- // isValid: false,
113
- // code: "META_FILE_NOT_FOUND",
114
- // },
115
- // }
116
- // }
117
- return validateCache({
118
- logger,
119
- compiledFileUrl,
120
- compileCacheStrategy,
121
- compileCacheSourcesValidation,
122
- compileCacheAssetsValidation,
123
- request,
124
- })
125
- },
126
- )
127
-
128
- if (!cacheValidity.isValid) {
129
- if (cacheValidity.code === "SOURCES_EMPTY") {
130
- logger.warn(`WARNING: meta.sources is empty for ${compiledFileUrl}`)
131
- }
132
-
133
- const metaIsValid = cacheValidity.meta.isValid
134
-
135
- const [compileTiming, compileResult] = await timeFunction("compile", () =>
136
- callCompile({
137
- logger,
138
- originalFileUrl,
139
- fileContentFallback,
140
- compile,
141
- }),
142
- )
143
-
144
- return {
145
- meta: metaIsValid ? cacheValidity.meta.data : null,
146
- compileResult,
147
- compileResultStatus: metaIsValid ? "updated" : "created",
148
- timing: {
149
- ...readCacheTiming,
150
- ...compileTiming,
151
- },
152
- }
153
- }
154
-
155
- const meta = cacheValidity.meta.data
156
- const { contentType, sources, assets } = meta
157
- return {
158
- meta,
159
- compileResult: {
160
- compiledSource: String(
161
- cacheValidity.compiledFile.data.compiledSourceBuffer,
162
- ),
163
- compiledEtag: cacheValidity.compiledFile.data.compiledEtag,
164
- compiledMtime: cacheValidity.compiledFile.data.compiledMtime,
165
- contentType,
166
- sources,
167
- assets,
168
- },
169
- compileResultStatus: "cached",
170
- timing: {
171
- ...readCacheTiming,
172
- },
173
- }
174
- }
175
-
176
- const callCompile = async ({
177
- logger,
178
- originalFileUrl,
179
- fileContentFallback,
180
- compile,
181
- }) => {
182
- logger.debug(`compile ${originalFileUrl}`)
183
-
184
- const codeBeforeCompile =
185
- compile.length === 0
186
- ? ""
187
- : await getCodeToCompile({ originalFileUrl, fileContentFallback })
188
-
189
- const compileReturnValue = await compile({
190
- code: codeBeforeCompile,
191
- map: undefined,
192
- })
193
- if (typeof compileReturnValue !== "object" || compileReturnValue === null) {
194
- throw new TypeError(
195
- `compile must return an object, got ${compileReturnValue}`,
196
- )
197
- }
198
- const {
199
- contentType,
200
- compiledSource,
201
- sources = [],
202
- sourcesContent = [],
203
- assets = [],
204
- assetsContent = [],
205
- responseHeaders,
206
- } = compileReturnValue
207
- if (typeof contentType !== "string") {
208
- throw new TypeError(
209
- `compile must return a contentType string, got ${contentType}`,
210
- )
211
- }
212
- if (typeof compiledSource !== "string") {
213
- throw new TypeError(
214
- `compile must return a compiledSource string, got ${compiledSource}`,
215
- )
216
- }
217
-
218
- return {
219
- contentType,
220
- compiledSource,
221
- sources,
222
- sourcesContent,
223
- assets,
224
- assetsContent,
225
- responseHeaders,
226
- }
227
- }
228
-
229
- const getCodeToCompile = async ({ originalFileUrl, fileContentFallback }) => {
230
- let fileContent
231
- if (fileContentFallback) {
232
- try {
233
- fileContent = await readFileContent(originalFileUrl)
234
- } catch (e) {
235
- if (e.code === "ENOENT") {
236
- fileContent = await fileContentFallback()
237
- } else {
238
- throw e
239
- }
240
- }
241
- } else {
242
- fileContent = await readFileContent(originalFileUrl)
243
- }
244
- return fileContent
245
- }
246
-
247
- const startAsap = async (fn, { logger, compiledFileUrl }) => {
248
- const metaJsonFileUrl = getMetaJsonFileUrl(compiledFileUrl)
249
- const metaJsonFilePath = urlToFileSystemPath(metaJsonFileUrl)
250
-
251
- logger.debug(`lock ${metaJsonFilePath}`)
252
- // in case this process try to concurrently access meta we wait for previous to be done
253
- const unlockLocal = await lockForRessource(metaJsonFilePath)
254
-
255
- let unlockInterProcessLock = () => {}
256
-
257
- try {
258
- return await fn()
259
- } finally {
260
- // we want to unlock in case of error too
261
- logger.debug(`unlock ${metaJsonFilePath}`)
262
- unlockLocal()
263
- unlockInterProcessLock()
264
- }
265
- }
1
+ import { urlToFileSystemPath } from "@jsenv/filesystem"
2
+ import { createDetailedMessage } from "@jsenv/logger"
3
+ import { timeStart, timeFunction } from "@jsenv/server"
4
+ import { readFileContent } from "./fs-optimized-for-cache.js"
5
+ import { validateCache } from "./validateCache.js"
6
+ import { getMetaJsonFileUrl } from "./compile-asset.js"
7
+ import { createLockRegistry } from "./createLockRegistry.js"
8
+
9
+ const { lockForRessource } = createLockRegistry()
10
+
11
+ export const getOrGenerateCompiledFile = async ({
12
+ logger,
13
+
14
+ projectDirectoryUrl,
15
+ originalFileUrl,
16
+ compiledFileUrl = originalFileUrl,
17
+ compileCacheStrategy,
18
+ compileCacheSourcesValidation,
19
+ compileCacheAssetsValidation,
20
+ fileContentFallback,
21
+ request,
22
+ compile,
23
+ }) => {
24
+ if (typeof projectDirectoryUrl !== "string") {
25
+ throw new TypeError(
26
+ `projectDirectoryUrl must be a string, got ${projectDirectoryUrl}`,
27
+ )
28
+ }
29
+ if (typeof originalFileUrl !== "string") {
30
+ throw new TypeError(
31
+ `originalFileUrl must be a string, got ${originalFileUrl}`,
32
+ )
33
+ }
34
+ if (!originalFileUrl.startsWith(projectDirectoryUrl)) {
35
+ throw new Error(
36
+ createDetailedMessage(`origin file must be inside project`, {
37
+ ["original file url"]: originalFileUrl,
38
+ ["project directory url"]: projectDirectoryUrl,
39
+ }),
40
+ )
41
+ }
42
+ if (typeof compiledFileUrl !== "string") {
43
+ throw new TypeError(
44
+ `compiledFileUrl must be a string, got ${compiledFileUrl}`,
45
+ )
46
+ }
47
+ if (!compiledFileUrl.startsWith(projectDirectoryUrl)) {
48
+ throw new Error(
49
+ createDetailedMessage(`compiled file must be inside project`, {
50
+ ["compiled file url"]: compiledFileUrl,
51
+ ["project directory url"]: projectDirectoryUrl,
52
+ }),
53
+ )
54
+ }
55
+ if (typeof compile !== "function") {
56
+ throw new TypeError(`compile must be a function, got ${compile}`)
57
+ }
58
+
59
+ const lockTimeEnd = timeStart("lock")
60
+ return startAsap(
61
+ async () => {
62
+ const lockTiming = lockTimeEnd()
63
+ const { meta, compileResult, compileResultStatus, timing } =
64
+ await computeCompileReport({
65
+ originalFileUrl,
66
+ compiledFileUrl,
67
+ compile,
68
+ fileContentFallback,
69
+ compileCacheStrategy,
70
+ compileCacheSourcesValidation,
71
+ compileCacheAssetsValidation,
72
+ request,
73
+ logger,
74
+ })
75
+
76
+ return {
77
+ meta,
78
+ compileResult,
79
+ compileResultStatus,
80
+ timing: {
81
+ ...lockTiming,
82
+ ...timing,
83
+ },
84
+ }
85
+ },
86
+ {
87
+ compiledFileUrl,
88
+ logger,
89
+ },
90
+ )
91
+ }
92
+
93
+ const computeCompileReport = async ({
94
+ originalFileUrl,
95
+ compiledFileUrl,
96
+ compile,
97
+ fileContentFallback,
98
+ compileCacheStrategy,
99
+ compileCacheSourcesValidation,
100
+ compileCacheAssetsValidation,
101
+ request,
102
+ logger,
103
+ }) => {
104
+ const [readCacheTiming, cacheValidity] = await timeFunction(
105
+ "read cache",
106
+ () => {
107
+ // if (!useFilesystemAsCache) {
108
+ // return {
109
+ // isValid: false,
110
+ // code: "META_FILE_NOT_FOUND",
111
+ // meta: {
112
+ // isValid: false,
113
+ // code: "META_FILE_NOT_FOUND",
114
+ // },
115
+ // }
116
+ // }
117
+ return validateCache({
118
+ logger,
119
+ compiledFileUrl,
120
+ compileCacheStrategy,
121
+ compileCacheSourcesValidation,
122
+ compileCacheAssetsValidation,
123
+ request,
124
+ })
125
+ },
126
+ )
127
+
128
+ if (!cacheValidity.isValid) {
129
+ if (cacheValidity.code === "SOURCES_EMPTY") {
130
+ logger.warn(`WARNING: meta.sources is empty for ${compiledFileUrl}`)
131
+ }
132
+
133
+ const metaIsValid = cacheValidity.meta.isValid
134
+
135
+ const [compileTiming, compileResult] = await timeFunction("compile", () =>
136
+ callCompile({
137
+ logger,
138
+ originalFileUrl,
139
+ fileContentFallback,
140
+ compile,
141
+ }),
142
+ )
143
+
144
+ return {
145
+ meta: metaIsValid ? cacheValidity.meta.data : null,
146
+ compileResult,
147
+ compileResultStatus: metaIsValid ? "updated" : "created",
148
+ timing: {
149
+ ...readCacheTiming,
150
+ ...compileTiming,
151
+ },
152
+ }
153
+ }
154
+
155
+ const meta = cacheValidity.meta.data
156
+ const { contentType, sources, assets, dependencies } = meta
157
+ return {
158
+ meta,
159
+ compileResult: {
160
+ compiledSource: String(
161
+ cacheValidity.compiledFile.data.compiledSourceBuffer,
162
+ ),
163
+ compiledEtag: cacheValidity.compiledFile.data.compiledEtag,
164
+ compiledMtime: cacheValidity.compiledFile.data.compiledMtime,
165
+ contentType,
166
+ sources,
167
+ assets,
168
+ dependencies,
169
+ },
170
+ compileResultStatus: "cached",
171
+ timing: {
172
+ ...readCacheTiming,
173
+ },
174
+ }
175
+ }
176
+
177
+ const callCompile = async ({
178
+ logger,
179
+ originalFileUrl,
180
+ fileContentFallback,
181
+ compile,
182
+ }) => {
183
+ logger.debug(`compile ${originalFileUrl}`)
184
+
185
+ const codeBeforeCompile =
186
+ compile.length === 0
187
+ ? ""
188
+ : await getCodeToCompile({ originalFileUrl, fileContentFallback })
189
+
190
+ const compileReturnValue = await compile({
191
+ code: codeBeforeCompile,
192
+ map: undefined,
193
+ })
194
+ if (typeof compileReturnValue !== "object" || compileReturnValue === null) {
195
+ throw new TypeError(
196
+ `compile must return an object, got ${compileReturnValue}`,
197
+ )
198
+ }
199
+ const {
200
+ contentType,
201
+ compiledSource,
202
+ sources = [],
203
+ sourcesContent = [],
204
+ assets = [],
205
+ assetsContent = [],
206
+ dependencies = [],
207
+ responseHeaders,
208
+ } = compileReturnValue
209
+ if (typeof contentType !== "string") {
210
+ throw new TypeError(
211
+ `compile must return a contentType string, got ${contentType}`,
212
+ )
213
+ }
214
+ if (typeof compiledSource !== "string") {
215
+ throw new TypeError(
216
+ `compile must return a compiledSource string, got ${compiledSource}`,
217
+ )
218
+ }
219
+
220
+ return {
221
+ contentType,
222
+ compiledSource,
223
+ sources,
224
+ sourcesContent,
225
+ assets,
226
+ assetsContent,
227
+ dependencies,
228
+ responseHeaders,
229
+ }
230
+ }
231
+
232
+ const getCodeToCompile = async ({ originalFileUrl, fileContentFallback }) => {
233
+ let fileContent
234
+ if (fileContentFallback) {
235
+ try {
236
+ fileContent = await readFileContent(originalFileUrl)
237
+ } catch (e) {
238
+ if (e.code === "ENOENT") {
239
+ fileContent = await fileContentFallback()
240
+ } else {
241
+ throw e
242
+ }
243
+ }
244
+ } else {
245
+ fileContent = await readFileContent(originalFileUrl)
246
+ }
247
+ return fileContent
248
+ }
249
+
250
+ const startAsap = async (fn, { logger, compiledFileUrl }) => {
251
+ const metaJsonFileUrl = getMetaJsonFileUrl(compiledFileUrl)
252
+ const metaJsonFilePath = urlToFileSystemPath(metaJsonFileUrl)
253
+
254
+ logger.debug(`lock ${metaJsonFilePath}`)
255
+ // in case this process try to concurrently access meta we wait for previous to be done
256
+ const unlockLocal = await lockForRessource(metaJsonFilePath)
257
+
258
+ let unlockInterProcessLock = () => {}
259
+
260
+ try {
261
+ return await fn()
262
+ } finally {
263
+ // we want to unlock in case of error too
264
+ logger.debug(`unlock ${metaJsonFilePath}`)
265
+ unlockLocal()
266
+ unlockInterProcessLock()
267
+ }
268
+ }