OLD | NEW |
---|---|
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 part of dart2js; | 5 part of dart2js; |
6 | 6 |
7 /** | 7 /** |
8 * [CompilerTask] for loading libraries and setting up the import/export scopes. | 8 * [CompilerTask] for loading libraries and setting up the import/export scopes. |
9 * | 9 * |
10 * The library loader uses four different kinds of URIs in different parts of | 10 * The library loader uses four different kinds of URIs in different parts of |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
106 * | 106 * |
107 * If the library is not already loaded, the method creates the | 107 * If the library is not already loaded, the method creates the |
108 * [LibraryElement] for the library and computes the import/export scope, | 108 * [LibraryElement] for the library and computes the import/export scope, |
109 * loading and computing the import/export scopes of all required libraries in | 109 * loading and computing the import/export scopes of all required libraries in |
110 * the process. The method handles cyclic dependency between libraries. | 110 * the process. The method handles cyclic dependency between libraries. |
111 * | 111 * |
112 * This is the main entry point for [LibraryLoader]. | 112 * This is the main entry point for [LibraryLoader]. |
113 */ | 113 */ |
114 // TODO(johnniwinther): Remove [canonicalUri] together with | 114 // TODO(johnniwinther): Remove [canonicalUri] together with |
115 // [Compiler.scanBuiltinLibrary]. | 115 // [Compiler.scanBuiltinLibrary]. |
116 LibraryElement loadLibrary(Uri resolvedUri, Node node, Uri canonicalUri); | 116 Future<LibraryElement> loadLibrary(Uri resolvedUri, Node node, |
117 Uri canonicalUri); | |
117 | 118 |
118 // TODO(johnniwinther): Remove this when patches don't need special parsing. | 119 // TODO(johnniwinther): Remove this when patches don't need special parsing. |
119 void registerLibraryFromTag(LibraryDependencyHandler handler, | 120 Future registerLibraryFromTag(LibraryDependencyHandler handler, |
120 LibraryElement library, | 121 LibraryElement library, |
121 LibraryDependency tag); | 122 LibraryDependency tag); |
122 | 123 |
123 /** | 124 /** |
124 * Adds the elements in the export scope of [importedLibrary] to the import | 125 * Adds the elements in the export scope of [importedLibrary] to the import |
125 * scope of [importingLibrary]. | 126 * scope of [importingLibrary]. |
126 */ | 127 */ |
127 // TODO(johnniwinther): Move handling of 'js_helper' to the library loader | 128 // TODO(johnniwinther): Move handling of 'js_helper' to the library loader |
128 // to remove this method from the [LibraryLoader] interface. | 129 // to remove this method from the [LibraryLoader] interface. |
129 void importLibrary(LibraryElement importingLibrary, | 130 void importLibrary(LibraryElement importingLibrary, |
130 LibraryElement importedLibrary, | 131 LibraryElement importedLibrary, |
131 Import tag); | 132 Import tag); |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
219 */ | 220 */ |
220 class LibraryLoaderTask extends LibraryLoader { | 221 class LibraryLoaderTask extends LibraryLoader { |
221 LibraryLoaderTask(Compiler compiler) : super(compiler); | 222 LibraryLoaderTask(Compiler compiler) : super(compiler); |
222 String get name => 'LibraryLoader'; | 223 String get name => 'LibraryLoader'; |
223 | 224 |
224 final Map<String, LibraryElement> libraryNames = | 225 final Map<String, LibraryElement> libraryNames = |
225 new LinkedHashMap<String, LibraryElement>(); | 226 new LinkedHashMap<String, LibraryElement>(); |
226 | 227 |
227 LibraryDependencyHandler currentHandler; | 228 LibraryDependencyHandler currentHandler; |
228 | 229 |
229 LibraryElement loadLibrary(Uri resolvedUri, Node node, Uri canonicalUri) { | 230 Future<LibraryElement> loadLibrary(Uri resolvedUri, Node node, Uri canonicalUr i) { |
ahe
2013/06/26 07:02:00
Long line.
Bob Nystrom
2013/06/27 00:38:18
Done.
| |
230 return measure(() { | 231 return measureAsync(() { |
ahe
2013/06/26 07:02:00
I think this should be measure
Bob Nystrom
2013/06/27 00:38:18
Done.
| |
231 assert(currentHandler == null); | 232 assert(currentHandler == null); |
232 currentHandler = new LibraryDependencyHandler(compiler); | 233 currentHandler = new LibraryDependencyHandler(compiler); |
233 LibraryElement library = | 234 return createLibrary(currentHandler, null, resolvedUri, node, canonicalUri ).then((library) { |
Bob Nystrom
2013/06/26 01:03:24
I'll fix these long lines.
ahe
2013/06/26 07:02:00
An then wrap this is in measure as well.
ahe
2013/06/26 07:02:00
Please restore the type of "library".
Bob Nystrom
2013/06/27 00:38:18
Done.
Bob Nystrom
2013/06/27 00:38:18
Done.
| |
234 createLibrary(currentHandler, null, resolvedUri, node, canonicalUri); | 235 currentHandler.computeExports(); |
235 currentHandler.computeExports(); | 236 currentHandler = null; |
236 currentHandler = null; | 237 return library; |
237 return library; | 238 }); |
238 }); | 239 }); |
239 } | 240 } |
240 | 241 |
241 /** | 242 /** |
242 * Processes the library tags in [library]. | 243 * Processes the library tags in [library]. |
243 * | 244 * |
244 * The imported/exported libraries are loaded and processed recursively but | 245 * The imported/exported libraries are loaded and processed recursively but |
245 * the import/export scopes are not set up. | 246 * the import/export scopes are not set up. |
246 */ | 247 */ |
247 void processLibraryTags(LibraryDependencyHandler handler, | 248 Future processLibraryTags(LibraryDependencyHandler handler, |
248 LibraryElement library) { | 249 LibraryElement library) { |
249 int tagState = TagState.NO_TAG_SEEN; | 250 int tagState = TagState.NO_TAG_SEEN; |
250 | 251 |
251 /** | 252 /** |
252 * If [value] is less than [tagState] complain and return | 253 * If [value] is less than [tagState] complain and return |
253 * [tagState]. Otherwise return the new value for [tagState] | 254 * [tagState]. Otherwise return the new value for [tagState] |
254 * (transition function for state machine). | 255 * (transition function for state machine). |
255 */ | 256 */ |
256 int checkTag(int value, LibraryTag tag) { | 257 int checkTag(int value, LibraryTag tag) { |
257 if (tagState > value) { | 258 if (tagState > value) { |
258 compiler.reportError(tag, 'out of order'); | 259 compiler.reportError(tag, 'out of order'); |
259 return tagState; | 260 return tagState; |
260 } | 261 } |
261 return TagState.NEXT[value]; | 262 return TagState.NEXT[value]; |
262 } | 263 } |
263 | 264 |
264 bool importsDartCore = false; | 265 bool importsDartCore = false; |
265 var libraryDependencies = new LinkBuilder<LibraryDependency>(); | 266 var libraryDependencies = new LinkBuilder<LibraryDependency>(); |
266 Uri base = library.entryCompilationUnit.script.uri; | 267 Uri base = library.entryCompilationUnit.script.uri; |
267 for (LibraryTag tag in library.tags.reverse()) { | 268 |
269 return Future.forEach(library.tags.reverse(), (tag) { | |
ahe
2013/06/26 07:02:00
I need to figure out what this does.
Bob Nystrom
2013/06/27 00:38:18
It should be semantically equivalent to the previo
| |
268 if (tag.isImport) { | 270 if (tag.isImport) { |
269 Import import = tag; | 271 Import import = tag; |
270 tagState = checkTag(TagState.IMPORT_OR_EXPORT, import); | 272 tagState = checkTag(TagState.IMPORT_OR_EXPORT, import); |
271 if (import.uri.dartString.slowToString() == 'dart:core') { | 273 if (import.uri.dartString.slowToString() == 'dart:core') { |
272 importsDartCore = true; | 274 importsDartCore = true; |
273 } | 275 } |
274 libraryDependencies.addLast(import); | 276 libraryDependencies.addLast(import); |
275 } else if (tag.isExport) { | 277 } else if (tag.isExport) { |
276 tagState = checkTag(TagState.IMPORT_OR_EXPORT, tag); | 278 tagState = checkTag(TagState.IMPORT_OR_EXPORT, tag); |
277 libraryDependencies.addLast(tag); | 279 libraryDependencies.addLast(tag); |
278 } else if (tag.isLibraryName) { | 280 } else if (tag.isLibraryName) { |
279 tagState = checkTag(TagState.LIBRARY, tag); | 281 tagState = checkTag(TagState.LIBRARY, tag); |
280 if (library.libraryTag != null) { | 282 if (library.libraryTag != null) { |
281 compiler.cancel("duplicated library declaration", node: tag); | 283 compiler.cancel("duplicated library declaration", node: tag); |
282 } else { | 284 } else { |
283 library.libraryTag = tag; | 285 library.libraryTag = tag; |
284 } | 286 } |
285 checkDuplicatedLibraryName(library); | 287 checkDuplicatedLibraryName(library); |
286 } else if (tag.isPart) { | 288 } else if (tag.isPart) { |
287 Part part = tag; | 289 Part part = tag; |
288 StringNode uri = part.uri; | 290 StringNode uri = part.uri; |
289 Uri resolvedUri = base.resolve(uri.dartString.slowToString()); | 291 Uri resolvedUri = base.resolve(uri.dartString.slowToString()); |
290 tagState = checkTag(TagState.SOURCE, part); | 292 tagState = checkTag(TagState.SOURCE, part); |
291 scanPart(part, resolvedUri, library); | 293 return scanPart(part, resolvedUri, library); |
292 } else { | 294 } else { |
293 compiler.internalError("Unhandled library tag.", node: tag); | 295 compiler.internalError("Unhandled library tag.", node: tag); |
294 } | 296 } |
295 } | 297 }).then((_) { |
296 | 298 // Apply patch, if any. |
297 // Apply patch, if any. | 299 if (library.isPlatformLibrary) { |
298 if (library.isPlatformLibrary) { | 300 return patchDartLibrary(handler, library, library.canonicalUri.path); |
299 patchDartLibrary(handler, library, library.canonicalUri.path); | 301 } |
300 } | 302 }).then((_) { |
301 | 303 // Import dart:core if not already imported. |
302 // Import dart:core if not already imported. | 304 if (!importsDartCore && !isDartCore(library.canonicalUri)) { |
303 if (!importsDartCore && !isDartCore(library.canonicalUri)) { | 305 return loadCoreLibrary(handler).then((coreLibrary) { |
304 handler.registerDependency(library, null, loadCoreLibrary(handler)); | 306 handler.registerDependency(library, null, coreLibrary); |
305 } | 307 }); |
306 | 308 } |
307 for (LibraryDependency tag in libraryDependencies.toLink()) { | 309 }).then((_) { |
308 registerLibraryFromTag(handler, library, tag); | 310 return Future.forEach(libraryDependencies.toLink(), (tag) { |
309 } | 311 return registerLibraryFromTag(handler, library, tag); |
312 }); | |
313 }); | |
310 } | 314 } |
311 | 315 |
312 void checkDuplicatedLibraryName(LibraryElement library) { | 316 void checkDuplicatedLibraryName(LibraryElement library) { |
313 LibraryName tag = library.libraryTag; | 317 LibraryName tag = library.libraryTag; |
314 if (tag != null) { | 318 if (tag != null) { |
315 String name = library.getLibraryOrScriptName(); | 319 String name = library.getLibraryOrScriptName(); |
316 LibraryElement existing = | 320 LibraryElement existing = |
317 libraryNames.putIfAbsent(name, () => library); | 321 libraryNames.putIfAbsent(name, () => library); |
318 if (!identical(existing, library)) { | 322 if (!identical(existing, library)) { |
319 Uri uri = library.entryCompilationUnit.script.uri; | 323 Uri uri = library.entryCompilationUnit.script.uri; |
320 compiler.reportMessage( | 324 compiler.reportMessage( |
321 compiler.spanFromSpannable(tag.name, uri), | 325 compiler.spanFromSpannable(tag.name, uri), |
322 MessageKind.DUPLICATED_LIBRARY_NAME.error({'libraryName': name}), | 326 MessageKind.DUPLICATED_LIBRARY_NAME.error({'libraryName': name}), |
323 api.Diagnostic.WARNING); | 327 api.Diagnostic.WARNING); |
324 Uri existingUri = existing.entryCompilationUnit.script.uri; | 328 Uri existingUri = existing.entryCompilationUnit.script.uri; |
325 compiler.reportMessage( | 329 compiler.reportMessage( |
326 compiler.spanFromSpannable(existing.libraryTag.name, existingUri), | 330 compiler.spanFromSpannable(existing.libraryTag.name, existingUri), |
327 MessageKind.DUPLICATED_LIBRARY_NAME.error({'libraryName': name}), | 331 MessageKind.DUPLICATED_LIBRARY_NAME.error({'libraryName': name}), |
328 api.Diagnostic.WARNING); | 332 api.Diagnostic.WARNING); |
329 } | 333 } |
330 } | 334 } |
331 } | 335 } |
332 | 336 |
333 bool isDartCore(Uri uri) => uri.scheme == "dart" && uri.path == "core"; | 337 bool isDartCore(Uri uri) => uri.scheme == "dart" && uri.path == "core"; |
334 | 338 |
335 /** | 339 /** |
336 * Lazily loads and returns the [LibraryElement] for the dart:core library. | 340 * Lazily loads and returns the [LibraryElement] for the dart:core library. |
337 */ | 341 */ |
338 LibraryElement loadCoreLibrary(LibraryDependencyHandler handler) { | 342 Future<LibraryElement> loadCoreLibrary(LibraryDependencyHandler handler) { |
339 if (compiler.coreLibrary == null) { | 343 if (compiler.coreLibrary != null) { |
340 Uri coreUri = new Uri(scheme: 'dart', path: 'core'); | 344 return new Future.value(compiler.coreLibrary); |
341 compiler.coreLibrary | |
342 = createLibrary(handler, null, coreUri, null, coreUri); | |
343 } | 345 } |
344 return compiler.coreLibrary; | 346 |
347 Uri coreUri = new Uri(scheme: 'dart', path: 'core'); | |
348 return createLibrary(handler, null, coreUri, null, coreUri).then((library) { | |
349 compiler.coreLibrary = library; | |
350 return library; | |
351 }); | |
345 } | 352 } |
346 | 353 |
347 void patchDartLibrary(LibraryDependencyHandler handler, | 354 Future patchDartLibrary(LibraryDependencyHandler handler, |
348 LibraryElement library, String dartLibraryPath) { | 355 LibraryElement library, String dartLibraryPath) { |
349 if (library.isPatched) return; | 356 if (library.isPatched) return new Future.value(); |
350 Uri patchUri = compiler.resolvePatchUri(dartLibraryPath); | 357 Uri patchUri = compiler.resolvePatchUri(dartLibraryPath); |
351 if (patchUri != null) { | 358 if (patchUri == null) return new Future.value(); |
352 compiler.patchParser.patchLibrary(handler, patchUri, library); | 359 |
353 } | 360 return compiler.patchParser.patchLibrary(handler, patchUri, library); |
354 } | 361 } |
355 | 362 |
356 /** | 363 /** |
357 * Handle a part tag in the scope of [library]. The [resolvedUri] given is | 364 * Handle a part tag in the scope of [library]. The [resolvedUri] given is |
358 * used as is, any URI resolution should be done beforehand. | 365 * used as is, any URI resolution should be done beforehand. |
359 */ | 366 */ |
360 void scanPart(Part part, Uri resolvedUri, LibraryElement library) { | 367 Future scanPart(Part part, Uri resolvedUri, LibraryElement library) { |
361 if (!resolvedUri.isAbsolute) throw new ArgumentError(resolvedUri); | 368 if (!resolvedUri.isAbsolute) throw new ArgumentError(resolvedUri); |
362 Uri readableUri = compiler.translateResolvedUri(library, resolvedUri, part); | 369 Uri readableUri = compiler.translateResolvedUri(library, resolvedUri, part); |
363 Script sourceScript = compiler.readScript(readableUri, part); | 370 return compiler.readScript(readableUri, part).then((sourceScript) { |
364 CompilationUnitElement unit = | 371 CompilationUnitElement unit = |
365 new CompilationUnitElementX(sourceScript, library); | 372 new CompilationUnitElementX(sourceScript, library); |
366 compiler.withCurrentElement(unit, () { | 373 compiler.withCurrentElement(unit, () { |
367 compiler.scanner.scan(unit); | 374 compiler.scanner.scan(unit); |
368 if (unit.partTag == null) { | 375 if (unit.partTag == null) { |
369 bool wasDiagnosticEmitted = false; | 376 bool wasDiagnosticEmitted = false; |
370 compiler.withCurrentElement(library, () { | 377 compiler.withCurrentElement(library, () { |
371 wasDiagnosticEmitted = | 378 wasDiagnosticEmitted = |
372 compiler.onDeprecatedFeature(part, 'missing part-of tag'); | 379 compiler.onDeprecatedFeature(part, 'missing part-of tag'); |
373 }); | 380 }); |
374 if (wasDiagnosticEmitted) { | 381 if (wasDiagnosticEmitted) { |
375 compiler.reportMessage( | 382 compiler.reportMessage( |
376 compiler.spanFromElement(unit), | 383 compiler.spanFromElement(unit), |
377 MessageKind.MISSING_PART_OF_TAG.error(), | 384 MessageKind.MISSING_PART_OF_TAG.error(), |
378 api.Diagnostic.INFO); | 385 api.Diagnostic.INFO); |
386 } | |
379 } | 387 } |
380 } | 388 }); |
381 }); | 389 }); |
382 } | 390 } |
383 | 391 |
384 /** | 392 /** |
385 * Handle an import/export tag by loading the referenced library and | 393 * Handle an import/export tag by loading the referenced library and |
386 * registering its dependency in [handler] for the computation of the import/ | 394 * registering its dependency in [handler] for the computation of the import/ |
387 * export scope. | 395 * export scope. |
388 */ | 396 */ |
389 void registerLibraryFromTag(LibraryDependencyHandler handler, | 397 Future registerLibraryFromTag(LibraryDependencyHandler handler, |
390 LibraryElement library, | 398 LibraryElement library, |
391 LibraryDependency tag) { | 399 LibraryDependency tag) { |
392 Uri base = library.entryCompilationUnit.script.uri; | 400 Uri base = library.entryCompilationUnit.script.uri; |
393 Uri resolvedUri = base.resolve(tag.uri.dartString.slowToString()); | 401 Uri resolvedUri = base.resolve(tag.uri.dartString.slowToString()); |
394 LibraryElement loadedLibrary = | 402 return createLibrary(handler, library, resolvedUri, tag.uri, resolvedUri) |
395 createLibrary(handler, library, resolvedUri, tag.uri, resolvedUri); | 403 .then((loadedLibrary) { |
396 handler.registerDependency(library, tag, loadedLibrary); | 404 handler.registerDependency(library, tag, loadedLibrary); |
397 | 405 if (!loadedLibrary.hasLibraryName()) { |
398 if (!loadedLibrary.hasLibraryName()) { | 406 compiler.withCurrentElement(library, () { |
399 compiler.withCurrentElement(library, () { | 407 compiler.reportError(tag == null ? null : tag.uri, |
400 compiler.reportError(tag == null ? null : tag.uri, | 408 'no library name found in ${loadedLibrary.canonicalUri}'); |
401 'no library name found in ${loadedLibrary.canonicalUri}'); | 409 }); |
402 }); | 410 } |
403 } | 411 }); |
404 } | 412 } |
405 | 413 |
406 /** | 414 /** |
407 * Create (or reuse) a library element for the library specified by the | 415 * Create (or reuse) a library element for the library specified by the |
408 * [resolvedUri]. | 416 * [resolvedUri]. |
409 * | 417 * |
410 * If a new library is created, the [handler] is notified. | 418 * If a new library is created, the [handler] is notified. |
411 */ | 419 */ |
412 // TODO(johnniwinther): Remove [canonicalUri] and make [resolvedUri] the | 420 // TODO(johnniwinther): Remove [canonicalUri] and make [resolvedUri] the |
413 // canonical uri when [Compiler.scanBuiltinLibrary] is removed. | 421 // canonical uri when [Compiler.scanBuiltinLibrary] is removed. |
414 LibraryElement createLibrary(LibraryDependencyHandler handler, | 422 Future<LibraryElement> createLibrary(LibraryDependencyHandler handler, |
415 LibraryElement importingLibrary, | 423 LibraryElement importingLibrary, |
416 Uri resolvedUri, Node node, Uri canonicalUri) { | 424 Uri resolvedUri, Node node, Uri canonicalUri) { |
417 bool newLibrary = false; | |
418 Uri readableUri = | 425 Uri readableUri = |
419 compiler.translateResolvedUri(importingLibrary, resolvedUri, node); | 426 compiler.translateResolvedUri(importingLibrary, resolvedUri, node); |
420 if (readableUri == null) return null; | 427 if (readableUri == null) return null; |
421 LibraryElement createLibrary() { | 428 |
422 newLibrary = true; | 429 if (canonicalUri != null) { |
423 Script script = compiler.readScript(readableUri, node); | 430 LibraryElement library = compiler.libraries[canonicalUri.toString()]; |
431 if (library != null) { | |
432 return new Future.value(library); | |
433 } | |
434 } | |
435 | |
436 return compiler.readScript(readableUri, node).then((script) { | |
424 LibraryElement element = new LibraryElementX(script, canonicalUri); | 437 LibraryElement element = new LibraryElementX(script, canonicalUri); |
425 handler.registerNewLibrary(element); | 438 handler.registerNewLibrary(element); |
426 native.maybeEnableNative(compiler, element); | 439 native.maybeEnableNative(compiler, element); |
427 return element; | 440 compiler.libraries[canonicalUri.toString()] = element; |
428 } | 441 return compiler.withCurrentElement(element, () { |
429 LibraryElement library; | 442 compiler.scanner.scanLibrary(element); |
430 if (canonicalUri == null) { | 443 return processLibraryTags(handler, element); |
431 library = createLibrary(); | 444 }).then((_) { |
432 } else { | 445 compiler.withCurrentElement(element, () { |
433 library = compiler.libraries.putIfAbsent(canonicalUri.toString(), | 446 handler.registerLibraryExports(element); |
434 createLibrary); | 447 compiler.onLibraryScanned(element, resolvedUri); |
435 } | 448 }); |
436 if (newLibrary) { | 449 return element; |
437 compiler.withCurrentElement(library, () { | |
438 compiler.scanner.scanLibrary(library); | |
439 processLibraryTags(handler, library); | |
440 handler.registerLibraryExports(library); | |
441 compiler.onLibraryScanned(library, resolvedUri); | |
442 }); | 450 }); |
443 } | 451 }); |
444 return library; | |
445 } | 452 } |
446 | 453 |
447 // TODO(johnniwinther): Remove this method when 'js_helper' is handled by | 454 // TODO(johnniwinther): Remove this method when 'js_helper' is handled by |
448 // [LibraryLoaderTask]. | 455 // [LibraryLoaderTask]. |
449 void importLibrary(LibraryElement importingLibrary, | 456 void importLibrary(LibraryElement importingLibrary, |
450 LibraryElement importedLibrary, | 457 LibraryElement importedLibrary, |
451 Import tag) { | 458 Import tag) { |
452 new ImportLink(tag, importedLibrary).importLibrary(compiler, | 459 new ImportLink(tag, importedLibrary).importLibrary(compiler, |
453 importingLibrary); | 460 importingLibrary); |
454 } | 461 } |
(...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
831 } | 838 } |
832 | 839 |
833 /** | 840 /** |
834 * Registers all top-level entities of [library] as starting point for the | 841 * Registers all top-level entities of [library] as starting point for the |
835 * fixed-point computation of the import/export scopes. | 842 * fixed-point computation of the import/export scopes. |
836 */ | 843 */ |
837 void registerLibraryExports(LibraryElement library) { | 844 void registerLibraryExports(LibraryElement library) { |
838 nodeMap[library].registerInitialExports(); | 845 nodeMap[library].registerInitialExports(); |
839 } | 846 } |
840 } | 847 } |
OLD | NEW |