| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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.js_emitter; | 5 part of dart2js.js_emitter; |
| 6 | 6 |
| 7 // TODO(ahe): Share these with js_helper.dart. | 7 // TODO(ahe): Share these with js_helper.dart. |
| 8 const FUNCTION_INDEX = 0; | 8 const FUNCTION_INDEX = 0; |
| 9 const NAME_INDEX = 1; | 9 const NAME_INDEX = 1; |
| 10 const CALL_NAME_INDEX = 2; | 10 const CALL_NAME_INDEX = 2; |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 116 'isolateName': namer.isolateName, | 116 'isolateName': namer.isolateName, |
| 117 'classIdExtractor': classIdExtractorAccess, | 117 'classIdExtractor': classIdExtractorAccess, |
| 118 'classFieldsExtractor': classFieldsExtractorAccess, | 118 'classFieldsExtractor': classFieldsExtractorAccess, |
| 119 'instanceFromClassId': instanceFromClassIdAccess, | 119 'instanceFromClassId': instanceFromClassIdAccess, |
| 120 'initializeEmptyInstance': initializeEmptyInstanceAccess, | 120 'initializeEmptyInstance': initializeEmptyInstanceAccess, |
| 121 'allClasses': allClassesAccess, | 121 'allClasses': allClassesAccess, |
| 122 'debugFastObjects': DEBUG_FAST_OBJECTS, | 122 'debugFastObjects': DEBUG_FAST_OBJECTS, |
| 123 'isTreeShakingDisabled': backend.isTreeShakingDisabled, | 123 'isTreeShakingDisabled': backend.isTreeShakingDisabled, |
| 124 'precompiled': precompiledAccess, | 124 'precompiled': precompiledAccess, |
| 125 'finishedClassesAccess': finishedClassesAccess, | 125 'finishedClassesAccess': finishedClassesAccess, |
| 126 'markerFun': emitter.markerFun, | |
| 127 'needsMixinSupport': emitter.needsMixinSupport, | 126 'needsMixinSupport': emitter.needsMixinSupport, |
| 128 'needsNativeSupport': program.needsNativeSupport, | 127 'needsNativeSupport': program.needsNativeSupport, |
| 129 'isInterceptorClass': namer.operatorIs(backend.jsInterceptorClass), | 128 'isInterceptorClass': namer.operatorIs(backend.jsInterceptorClass), |
| 130 'isObject' : namer.operatorIs(compiler.objectClass), | 129 'isObject' : namer.operatorIs(compiler.objectClass), |
| 131 'specProperty': js.string(namer.nativeSpecProperty), | 130 'specProperty': js.string(namer.nativeSpecProperty), |
| 132 'trivialNsmHandlers': emitter.buildTrivialNsmHandlers(), | 131 'trivialNsmHandlers': emitter.buildTrivialNsmHandlers(), |
| 133 'hasRetainedMetadata': backend.hasRetainedMetadata, | 132 'hasRetainedMetadata': backend.hasRetainedMetadata, |
| 134 'types': typesAccess, | 133 'types': typesAccess, |
| 135 'objectClassName': js.string(namer.runtimeTypeName(compiler.objectClass)), | 134 'objectClassName': js.string(namer.runtimeTypeName(compiler.objectClass)), |
| 136 'needsStructuredMemberInfo': emitter.needsStructuredMemberInfo, | 135 'needsStructuredMemberInfo': emitter.needsStructuredMemberInfo, |
| (...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 398 // class. The minifier together with noSuchMethod can put methods on | 397 // class. The minifier together with noSuchMethod can put methods on |
| 399 // the Object.prototype object, and they show through here, so we check | 398 // the Object.prototype object, and they show through here, so we check |
| 400 // that we have a string. | 399 // that we have a string. |
| 401 if (!superclass || typeof superclass != "string") { | 400 if (!superclass || typeof superclass != "string") { |
| 402 // Inlined special case of InheritFrom here for performance reasons. | 401 // Inlined special case of InheritFrom here for performance reasons. |
| 403 // Fix up the the Dart Object class' prototype. | 402 // Fix up the the Dart Object class' prototype. |
| 404 var constructor = allClasses[cls]; | 403 var constructor = allClasses[cls]; |
| 405 var prototype = constructor.prototype; | 404 var prototype = constructor.prototype; |
| 406 prototype.constructor = constructor; | 405 prototype.constructor = constructor; |
| 407 prototype.#isObject = constructor; | 406 prototype.#isObject = constructor; |
| 408 prototype.#deferredAction = #markerFun; | 407 prototype.#deferredAction = function() {}; |
| 409 return; | 408 return; |
| 410 } | 409 } |
| 411 finishClass(superclass); | 410 finishClass(superclass); |
| 412 var superConstructor = allClasses[superclass]; | 411 var superConstructor = allClasses[superclass]; |
| 413 | 412 |
| 414 if (!superConstructor) { | 413 if (!superConstructor) { |
| 415 superConstructor = existingIsolateProperties[superclass]; | 414 superConstructor = existingIsolateProperties[superclass]; |
| 416 } | 415 } |
| 417 | 416 |
| 418 var constructor = allClasses[cls]; | 417 var constructor = allClasses[cls]; |
| 419 var prototype = inheritFrom(constructor, superConstructor); | 418 var prototype = inheritFrom(constructor, superConstructor); |
| 420 | 419 |
| 420 if (#needsMixinSupport) { |
| 421 if (mixinPrototype) { |
| 422 prototype.#deferredAction |
| 423 = mixinDeferredActionHelper(mixinPrototype, prototype); |
| 424 } |
| 425 } |
| 426 |
| 421 if (#needsNativeSupport) { | 427 if (#needsNativeSupport) { |
| 422 if (Object.prototype.hasOwnProperty.call(prototype, #specProperty)) { | 428 if (Object.prototype.hasOwnProperty.call(prototype, #specProperty)) { |
| 423 #nativeInfoHandler; | 429 #nativeInfoHandler; |
| 424 // As native classes can come into existence without a constructor | 430 // As native classes can come into existence without a constructor |
| 425 // call, we have to ensure that the class has been fully | 431 // call, we have to ensure that the class has been fully |
| 426 // initialized. | 432 // initialized. |
| 427 if (constructor.prototype.#deferredAction) | 433 prototype.#deferredAction(); |
| 428 finishAddStubsHelper(constructor.prototype); | |
| 429 } | 434 } |
| 430 } | 435 } |
| 431 // Interceptors (or rather their prototypes) are also used without | 436 // Interceptors (or rather their prototypes) are also used without |
| 432 // first instantiating them first. | 437 // first instantiating them first. |
| 433 if (prototype.#isInterceptorClass && | 438 if (prototype.#isInterceptorClass) { |
| 434 constructor.prototype.#deferredAction) { | 439 prototype.#deferredAction(); |
| 435 finishAddStubsHelper(constructor.prototype); | |
| 436 } | 440 } |
| 437 } | 441 } |
| 438 | 442 |
| 439 #trivialNsmHandlers; | 443 #trivialNsmHandlers; |
| 440 | 444 |
| 441 var properties = Object.keys(processedClasses.pending); | 445 var properties = Object.keys(processedClasses.pending); |
| 442 for (var i = 0; i < properties.length; i++) finishClass(properties[i]); | 446 for (var i = 0; i < properties.length; i++) finishClass(properties[i]); |
| 443 } | 447 } |
| 444 | 448 |
| 449 // Generic handler for deferred class setup. The handler updates the |
| 450 // prototype that it is installed on (it traverses the prototype chain |
| 451 // of [this] to find itself) and then removes itself. It recurses by |
| 452 // calling deferred handling again, which terminates on Object due to |
| 453 // the final handler. |
| 454 function finishAddStubsHelper() { |
| 455 var prototype = this; |
| 456 // Find the actual prototype that this handler is installed on. |
| 457 while (!prototype.hasOwnProperty(#deferredActionString)) { |
| 458 prototype = prototype.__proto__; |
| 459 } |
| 460 delete prototype.#deferredAction; // Intended to make it slow, too. |
| 461 var properties = Object.keys(prototype); |
| 462 for (var index = 0; index < properties.length; index++) { |
| 463 var property = properties[index]; |
| 464 var firstChar = property.charCodeAt(0); |
| 465 var elem; |
| 466 // We have to filter out some special properties that are used for |
| 467 // metadata in descriptors. Currently, we filter everything that |
| 468 // starts with + or *. This has to stay in sync with the special |
| 469 // properties that are used by processClassData below. |
| 470 if (property !== "${namer.classDescriptorProperty}" && |
| 471 property !== "$reflectableField" && |
| 472 firstChar !== 43 && // 43 is aka "+". |
| 473 firstChar !== 42 && // 42 is aka "*" |
| 474 (elem = prototype[property]) != null && |
| 475 elem.constructor === Array && |
| 476 property !== "<>") { |
| 477 addStubs(prototype, elem, property, false, []); |
| 478 } |
| 479 } |
| 480 convertToFastObject(prototype); |
| 481 prototype = prototype.__proto__; |
| 482 // Call other handlers. |
| 483 prototype.#deferredAction(); |
| 484 } |
| 445 | 485 |
| 446 // For convenience, this method can be called with a prototype as argument | 486 if (#needsMixinSupport) { |
| 447 // or, if it was bound to an object, by invoking it as a method. Therefore, | 487 // Returns a deferred class setup handler that first invokes the |
| 448 // if prototype is undefined, this is used as prototype. | 488 // handler on [mixinPrototype] and then resumes handling on |
| 449 function finishAddStubsHelper(prototype) { | 489 // [targetPrototype]. If [targetPrototype] already has a handler |
| 450 var prototype = prototype || this; | 490 // installed, the handler is preserved in the generated closure and |
| 451 var object; | 491 // thus can be safely overwritten. |
| 452 while (prototype.#deferredAction != #markerFun) { | 492 function mixinDeferredActionHelper(mixinPrototype, targetPrototype) { |
| 453 if (prototype.hasOwnProperty(#deferredActionString)) { | 493 var chain; |
| 454 delete prototype.#deferredAction; // Intended to make it slow, too. | 494 if (targetPrototype.hasOwnProperty(#deferredActionString)) { |
| 455 var properties = Object.keys(prototype); | 495 chain = targetPrototype.#deferredAction; |
| 456 for (var index = 0; index < properties.length; index++) { | 496 } |
| 457 var property = properties[index]; | 497 return function foo() { |
| 458 var firstChar = property.charCodeAt(0); | 498 var prototype = this; |
| 459 var elem; | 499 // Find the actual prototype that this handler is installed on. |
| 460 // We have to filter out some special properties that are used for | 500 while (!prototype.hasOwnProperty(#deferredActionString)) { |
| 461 // metadata in descriptors. Currently, we filter everything that | 501 prototype = prototype.__proto__; |
| 462 // starts with + or *. This has to stay in sync with the special | |
| 463 // properties that are used by processClassData below. | |
| 464 if (property !== "${namer.classDescriptorProperty}" && | |
| 465 property !== "$reflectableField" && | |
| 466 firstChar !== 43 && // 43 is aka "+". | |
| 467 firstChar !== 42 && // 42 is aka "*" | |
| 468 (elem = prototype[property]) != null && | |
| 469 elem.constructor === Array && | |
| 470 property !== "<>") { | |
| 471 addStubs(prototype, elem, property, false, []); | |
| 472 } | |
| 473 } | 502 } |
| 474 convertToFastObject(prototype); | 503 if (chain) { |
| 504 prototype.#deferredAction = chain; |
| 505 } else { |
| 506 delete prototype.#deferredAction; |
| 507 convertToFastObject(prototype); |
| 508 } |
| 509 mixinPrototype.#deferredAction(); |
| 510 prototype.#deferredAction(); |
| 475 } | 511 } |
| 476 prototype = prototype.__proto__; | |
| 477 } | 512 } |
| 478 } | 513 } |
| 479 | 514 |
| 480 function processClassData(cls, descriptor, processedClasses) { | 515 function processClassData(cls, descriptor, processedClasses) { |
| 481 descriptor = convertToSlowObject(descriptor); // Use a slow object. | 516 descriptor = convertToSlowObject(descriptor); // Use a slow object. |
| 482 var previousProperty; | 517 var previousProperty; |
| 483 var properties = Object.keys(descriptor); | 518 var properties = Object.keys(descriptor); |
| 484 var hasDeferredWork = false; | 519 var hasDeferredWork = false; |
| 485 var shouldDeferWork = | 520 var shouldDeferWork = |
| 486 supportsDirectProtoAccess && cls != #objectClassName; | 521 supportsDirectProtoAccess && cls != #objectClassName; |
| (...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 804 (function() { | 839 (function() { |
| 805 var result = $array[$index]; | 840 var result = $array[$index]; |
| 806 if ($check) { | 841 if ($check) { |
| 807 throw new Error( | 842 throw new Error( |
| 808 name + ": expected value of type \'$type\' at index " + ($index) + | 843 name + ": expected value of type \'$type\' at index " + ($index) + |
| 809 " but got " + (typeof result)); | 844 " but got " + (typeof result)); |
| 810 } | 845 } |
| 811 return result; | 846 return result; |
| 812 })()'''; | 847 })()'''; |
| 813 } | 848 } |
| OLD | NEW |