Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(22)

Side by Side Diff: pkg/compiler/lib/src/js_emitter/old_emitter/setup_program_builder.dart

Issue 1024523003: dart2js: rename and refactor reflection_data_parser. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « pkg/compiler/lib/src/js_emitter/old_emitter/reflection_data_parser.dart ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 part of dart2js.js_emitter;
6
7 // TODO(ahe): Share these with js_helper.dart.
8 const FUNCTION_INDEX = 0;
9 const NAME_INDEX = 1;
10 const CALL_NAME_INDEX = 2;
11 const REQUIRED_PARAMETER_INDEX = 3;
12 const OPTIONAL_PARAMETER_INDEX = 4;
13 const DEFAULT_ARGUMENTS_INDEX = 5;
14
15 const bool VALIDATE_DATA = false;
16
17 const RANGE1_SIZE = RANGE1_LAST - RANGE1_FIRST + 1;
18 const RANGE2_SIZE = RANGE2_LAST - RANGE2_FIRST + 1;
19 const RANGE1_ADJUST = - (FIRST_FIELD_CODE - RANGE1_FIRST);
20 const RANGE2_ADJUST = - (FIRST_FIELD_CODE + RANGE1_SIZE - RANGE2_FIRST);
21 const RANGE3_ADJUST =
22 - (FIRST_FIELD_CODE + RANGE1_SIZE + RANGE2_SIZE - RANGE3_FIRST);
23
24 String get setupProgramName => 'setupProgram';
25
26
27 jsAst.Statement buildSetupProgram(Program program, Compiler compiler,
28 JavaScriptBackend backend,
29 Namer namer,
30 OldEmitter emitter) {
31
32 jsAst.Expression typeInformationAccess =
33 emitter.generateEmbeddedGlobalAccess(embeddedNames.TYPE_INFORMATION);
34 jsAst.Expression globalFunctionsAccess =
35 emitter.generateEmbeddedGlobalAccess(embeddedNames.GLOBAL_FUNCTIONS);
36 jsAst.Expression staticsAccess =
37 emitter.generateEmbeddedGlobalAccess(embeddedNames.STATICS);
38 jsAst.Expression interceptedNamesAccess =
39 emitter.generateEmbeddedGlobalAccess(embeddedNames.INTERCEPTED_NAMES);
40 jsAst.Expression mangledGlobalNamesAccess =
41 emitter.generateEmbeddedGlobalAccess(embeddedNames.MANGLED_GLOBAL_NAMES);
42 jsAst.Expression mangledNamesAccess =
43 emitter.generateEmbeddedGlobalAccess(embeddedNames.MANGLED_NAMES);
44 jsAst.Expression librariesAccess =
45 emitter.generateEmbeddedGlobalAccess(embeddedNames.LIBRARIES);
46 jsAst.Expression typesAccess =
47 emitter.generateEmbeddedGlobalAccess(embeddedNames.TYPES);
48 jsAst.Expression createNewIsolateFunctionAccess =
49 emitter.generateEmbeddedGlobalAccess(embeddedNames.CREATE_NEW_ISOLATE);
50 jsAst.Expression classIdExtractorAccess =
51 emitter.generateEmbeddedGlobalAccess(embeddedNames.CLASS_ID_EXTRACTOR);
52 jsAst.Expression allClassesAccess =
53 emitter.generateEmbeddedGlobalAccess(embeddedNames.ALL_CLASSES);
54 jsAst.Expression precompiledAccess =
55 emitter.generateEmbeddedGlobalAccess(embeddedNames.PRECOMPILED);
56 jsAst.Expression finishedClassesAccess =
57 emitter.generateEmbeddedGlobalAccess(embeddedNames.FINISHED_CLASSES);
58 jsAst.Expression interceptorsByTagAccess =
59 emitter.generateEmbeddedGlobalAccess(embeddedNames.INTERCEPTORS_BY_TAG);
60 jsAst.Expression leafTagsAccess =
61 emitter.generateEmbeddedGlobalAccess(embeddedNames.LEAF_TAGS);
62 jsAst.Expression initializeEmptyInstanceAccess =
63 emitter.generateEmbeddedGlobalAccess(
64 embeddedNames.INITIALIZE_EMPTY_INSTANCE);
65 jsAst.Expression classFieldsExtractorAccess =
66 emitter.generateEmbeddedGlobalAccess(
67 embeddedNames.CLASS_FIELDS_EXTRACTOR);
68 jsAst.Expression instanceFromClassIdAccess =
69 emitter.generateEmbeddedGlobalAccess(
70 embeddedNames.INSTANCE_FROM_CLASS_ID);
71
72 String reflectableField = namer.reflectableField;
73 String reflectionInfoField = namer.reflectionInfoField;
74 String reflectionNameField = namer.reflectionNameField;
75 String metadataIndexField = namer.metadataIndexField;
76 String defaultValuesField = namer.defaultValuesField;
77 String methodsWithOptionalArgumentsField =
78 namer.methodsWithOptionalArgumentsField;
79 String unmangledNameIndex = backend.mustRetainMetadata
80 ? ' 3 * optionalParameterCount + 2 * requiredParameterCount + 3'
81 : ' 2 * optionalParameterCount + requiredParameterCount + 3';
82 String receiverParamName = compiler.enableMinification ? "r" : "receiver";
83 String valueParamName = compiler.enableMinification ? "v" : "value";
84 String space = compiler.enableMinification ? "" : " ";
85 String _ = space;
86
87 String specProperty = '"${namer.nativeSpecProperty}"'; // "%"
88 jsAst.Expression nativeInfoAccess = js('prototype[$specProperty]', []);
89 jsAst.Expression constructorAccess = js('constructor', []);
90 Function subclassReadGenerator =
91 (jsAst.Expression subclass) => js('allClasses[#]', subclass);
92 jsAst.Statement nativeInfoHandler = emitter.
93 buildNativeInfoHandler(nativeInfoAccess, constructorAccess,
94 subclassReadGenerator, interceptorsByTagAccess,
95 leafTagsAccess);
96
97 Map<String, dynamic> holes =
98 {'needsClassSupport': emitter.needsClassSupport,
99 'libraries': librariesAccess,
100 'mangledNames': mangledNamesAccess,
101 'mangledGlobalNames': mangledGlobalNamesAccess,
102 'statics': staticsAccess,
103 'typeInformation': typeInformationAccess,
104 'globalFunctions': globalFunctionsAccess,
105 'enabledInvokeOn': compiler.enabledInvokeOn,
106 'interceptedNames': interceptedNamesAccess,
107 'interceptedNamesSet': emitter.generateInterceptedNamesSet(),
108 'notInCspMode': !compiler.useContentSecurityPolicy,
109 'inCspMode': compiler.useContentSecurityPolicy,
110 'deferredAction': namer.deferredAction,
111 'hasIsolateSupport': program.hasIsolateSupport,
112 'fieldNamesProperty': js.string(OldEmitter.FIELD_NAMES_PROPERTY_NAME),
113 'hasIncrementalSupport': compiler.hasIncrementalSupport,
114 'incrementalHelper': namer.accessIncrementalHelper,
115 'createNewIsolateFunction': createNewIsolateFunctionAccess,
116 'isolateName': namer.isolateName,
117 'classIdExtractor': classIdExtractorAccess,
118 'classFieldsExtractor': classFieldsExtractorAccess,
119 'instanceFromClassId': instanceFromClassIdAccess,
120 'initializeEmptyInstance': initializeEmptyInstanceAccess,
121 'allClasses': allClassesAccess,
122 'debugFastObjects': DEBUG_FAST_OBJECTS,
123 'isTreeShakingDisabled': backend.isTreeShakingDisabled,
124 'precompiled': precompiledAccess,
125 'finishedClassesAccess': finishedClassesAccess,
126 'markerFun': emitter.markerFun,
127 'needsMixinSupport': emitter.needsMixinSupport,
128 'needsNativeSupport': program.needsNativeSupport,
129 'isInterceptorClass': namer.operatorIs(backend.jsInterceptorClass),
130 'isObject' : namer.operatorIs(compiler.objectClass),
131 'specProperty': js.string(namer.nativeSpecProperty),
132 'trivialNsmHandlers': emitter.buildTrivialNsmHandlers(),
133 'hasRetainedMetadata': backend.hasRetainedMetadata,
134 'types': typesAccess,
135 'objectClassName': js.string(namer.runtimeTypeName(compiler.objectClass)),
136 'needsStructuredMemberInfo': emitter.needsStructuredMemberInfo,
137 'usesMangledNames':
138 compiler.mirrorsLibrary != null || compiler.enabledFunctionApply,
139 'tearOffCode': buildTearOffCode(backend),
140 'nativeInfoHandler': nativeInfoHandler,
141 'operatorIsPrefix' : js.string(namer.operatorIsPrefix),
142 'deferredActionString': js.string(namer.deferredAction)};
143
144 String skeleton = '''
145 function $setupProgramName(programData) {
146 "use strict";
147 if (#needsClassSupport) {
148
149 function generateAccessor(fieldDescriptor, accessors, cls) {
150 var fieldInformation = fieldDescriptor.split("-");
151 var field = fieldInformation[0];
152 var len = field.length;
153 var code = field.charCodeAt(len - 1);
154 var reflectable;
155 if (fieldInformation.length > 1) reflectable = true;
156 else reflectable = false;
157 code = ((code >= $RANGE1_FIRST) && (code <= $RANGE1_LAST))
158 ? code - $RANGE1_ADJUST
159 : ((code >= $RANGE2_FIRST) && (code <= $RANGE2_LAST))
160 ? code - $RANGE2_ADJUST
161 : ((code >= $RANGE3_FIRST) && (code <= $RANGE3_LAST))
162 ? code - $RANGE3_ADJUST
163 : $NO_FIELD_CODE;
164
165 if (code) { // needsAccessor
166 var getterCode = code & 3;
167 var setterCode = code >> 2;
168 var accessorName = field = field.substring(0, len - 1);
169
170 var divider = field.indexOf(":");
171 if (divider > 0) { // Colon never in first position.
172 accessorName = field.substring(0, divider);
173 field = field.substring(divider + 1);
174 }
175
176 if (getterCode) { // needsGetter
177 var args = (getterCode & 2) ? "$receiverParamName" : "";
178 var receiver = (getterCode & 1) ? "this" : "$receiverParamName";
179 var body = "return " + receiver + "." + field;
180 var property =
181 cls + ".prototype.${namer.getterPrefix}" + accessorName + "=";
182 var fn = "function(" + args + "){" + body + "}";
183 if (reflectable)
184 accessors.push(property + "\$reflectable(" + fn + ");\\n");
185 else
186 accessors.push(property + fn + ";\\n");
187 }
188
189 if (setterCode) { // needsSetter
190 var args = (setterCode & 2)
191 ? "$receiverParamName,${_}$valueParamName"
192 : "$valueParamName";
193 var receiver = (setterCode & 1) ? "this" : "$receiverParamName";
194 var body = receiver + "." + field + "$_=$_$valueParamName";
195 var property =
196 cls + ".prototype.${namer.setterPrefix}" + accessorName + "=";
197 var fn = "function(" + args + "){" + body + "}";
198 if (reflectable)
199 accessors.push(property + "\$reflectable(" + fn + ");\\n");
200 else
201 accessors.push(property + fn + ";\\n");
202 }
203 }
204
205 return field;
206 }
207
208 // First the class name, then the field names in an array and the members
209 // (inside an Object literal).
210 // The caller can also pass in the constructor as a function if needed.
211 //
212 // Example:
213 // defineClass("A", ["x", "y"], {
214 // foo\$1: function(y) {
215 // print(this.x + y);
216 // },
217 // bar\$2: function(t, v) {
218 // this.x = t - v;
219 // },
220 // });
221 function defineClass(name, fields) {
222 var accessors = [];
223
224 var str = "function " + name + "(";
225 var body = "";
226 if (#hasIsolateSupport) { var fieldNames = ""; }
227
228 for (var i = 0; i < fields.length; i++) {
229 if(i != 0) str += ", ";
230
231 var field = generateAccessor(fields[i], accessors, name);
232 if (#hasIsolateSupport) { fieldNames += "'" + field + "',"; }
233 var parameter = "p_" + field;
234 str += parameter;
235 body += ("this." + field + " = " + parameter + ";\\n");
236 }
237 if (supportsDirectProtoAccess) {
238 body += "this." + #deferredActionString + "();";
239 }
240 str += ") {\\n" + body + "}\\n";
241 str += name + ".builtin\$cls=\\"" + name + "\\";\\n";
242 str += "\$desc=\$collectedClasses." + name + "[1];\\n";
243 str += name + ".prototype = \$desc;\\n";
244 if (typeof defineClass.name != "string") {
245 str += name + ".name=\\"" + name + "\\";\\n";
246 }
247 if (#hasIsolateSupport) {
248 str += name + "." + #fieldNamesProperty + "=[" + fieldNames
249 + "];\\n";
250 }
251 str += accessors.join("");
252
253 return str;
254 }
255
256 if (#hasIncrementalSupport) {
257 #incrementalHelper.defineClass = defineClass;
258 }
259
260 if (#hasIsolateSupport) {
261 #createNewIsolateFunction = function() { return new #isolateName(); };
262
263 #classIdExtractor = function(o) { return o.constructor.name; };
264
265 #classFieldsExtractor = function(o) {
266 var fieldNames = o.constructor.#fieldNamesProperty;
267 if (!fieldNames) return []; // TODO(floitsch): do something else here.
268 var result = [];
269 result.length = fieldNames.length;
270 for (var i = 0; i < fieldNames.length; i++) {
271 result[i] = o[fieldNames[i]];
272 }
273 return result;
274 };
275
276 #instanceFromClassId = function(name) { return new #allClasses[name](); };
277
278 #initializeEmptyInstance = function(name, o, fields) {
279 #allClasses[name].apply(o, fields);
280 return o; //
281 }
282 }
283
284 // If the browser supports changing the prototype via __proto__, we make
285 // use of that feature. Otherwise, we copy the properties into a new
286 // constructor.
287 var inheritFrom = supportsDirectProtoAccess ?
288 function(constructor, superConstructor) {
289 var prototype = constructor.prototype;
290 prototype.__proto__ = superConstructor.prototype;
291 // Use a function for `true` here, as functions are stored in the
292 // hidden class and not as properties in the object.
293 prototype.constructor = constructor;
294 prototype[#operatorIsPrefix + constructor.name] = constructor;
295 return convertToFastObject(prototype);
296 } :
297 function() {
298 function tmp() {}
299 return function (constructor, superConstructor) {
300 tmp.prototype = superConstructor.prototype;
301 var object = new tmp();
302 convertToSlowObject(object);
303 var properties = constructor.prototype;
304 var members = Object.keys(properties);
305 for (var i = 0; i < members.length; i++) {
306 var member = members[i];
307 object[member] = properties[member];
308 }
309 // Use a function for `true` here, as functions are stored in the
310 // hidden class and not as properties in the object.
311 object[#operatorIsPrefix + constructor.name] = constructor;
312 object.constructor = constructor;
313 constructor.prototype = object;
314 return object;
315 };
316 }();
317
318 if (#hasIncrementalSupport) {
319 #incrementalHelper.inheritFrom = inheritFrom;
320 }
321
322 // Class descriptions are collected in a JS object.
323 // 'finishClasses' takes all collected descriptions and sets up
324 // the prototype.
325 // Once set up, the constructors prototype field satisfy:
326 // - it contains all (local) members.
327 // - its internal prototype (__proto__) points to the superclass'
328 // prototype field.
329 // - the prototype's constructor field points to the JavaScript
330 // constructor.
331 // For engines where we have access to the '__proto__' we can manipulate
332 // the object literal directly. For other engines we have to create a new
333 // object and copy over the members.
334 function finishClasses(processedClasses) {
335 if (#debugFastObjects)
336 print("Number of classes: " +
337 Object.getOwnPropertyNames(processedClasses.collected).length);
338
339 var allClasses = #allClasses;
340
341 if (#inCspMode) {
342 var constructors = #precompiled(processedClasses.collected);
343 }
344
345 if (#notInCspMode) {
346 processedClasses.combinedConstructorFunction +=
347 "return [\\n" + processedClasses.constructorsList.join(",\\n ") +
348 "\\n]";
349 var constructors =
350 new Function("\$collectedClasses",
351 processedClasses.combinedConstructorFunction)
352 (processedClasses.collected);
353 processedClasses.combinedConstructorFunction = null;
354 }
355
356 for (var i = 0; i < constructors.length; i++) {
357 var constructor = constructors[i];
358 var cls = constructor.name;
359 var desc = processedClasses.collected[cls];
360 var globalObject = desc[0];
361 desc = desc[1];
362 if (#isTreeShakingDisabled)
363 constructor["${namer.metadataField}"] = desc;
364 allClasses[cls] = constructor;
365 globalObject[cls] = constructor;
366 }
367 constructors = null;
368
369 var finishedClasses = #finishedClassesAccess;
370
371 function finishClass(cls) {
372
373 if (finishedClasses[cls]) return;
374 finishedClasses[cls] = true;
375
376 var superclass = processedClasses.pending[cls];
377
378 if (#needsMixinSupport) {
379 if (superclass && superclass.indexOf("+") > 0) {
380 var s = superclass.split("+");
381 superclass = s[0];
382 var mixinClass = s[1];
383 finishClass(mixinClass);
384 var mixin = allClasses[mixinClass];
385 var mixinPrototype = mixin.prototype;
386 var clsPrototype = allClasses[cls].prototype;
387
388 var properties = Object.keys(mixinPrototype);
389 for (var i = 0; i < properties.length; i++) {
390 var d = properties[i];
391 if (!hasOwnProperty.call(clsPrototype, d))
392 clsPrototype[d] = mixinPrototype[d];
393 }
394 }
395 }
396
397 // The superclass is only false (empty string) for the Dart Object
398 // class. The minifier together with noSuchMethod can put methods on
399 // the Object.prototype object, and they show through here, so we check
400 // that we have a string.
401 if (!superclass || typeof superclass != "string") {
402 // Inlined special case of InheritFrom here for performance reasons.
403 // Fix up the the Dart Object class' prototype.
404 var constructor = allClasses[cls];
405 var prototype = constructor.prototype;
406 prototype.constructor = constructor;
407 prototype.#isObject = constructor;
408 prototype.#deferredAction = #markerFun;
409 return;
410 }
411 finishClass(superclass);
412 var superConstructor = allClasses[superclass];
413
414 if (!superConstructor) {
415 superConstructor = existingIsolateProperties[superclass];
416 }
417
418 var constructor = allClasses[cls];
419 var prototype = inheritFrom(constructor, superConstructor);
420
421 if (#needsNativeSupport) {
422 if (Object.prototype.hasOwnProperty.call(prototype, #specProperty)) {
423 #nativeInfoHandler;
424 // As native classes can come into existence without a constructor
425 // call, we have to ensure that the class has been fully
426 // initialized.
427 if (constructor.prototype.#deferredAction)
428 finishAddStubsHelper(constructor.prototype);
429 }
430 }
431 // Interceptors (or rather their prototypes) are also used without
432 // first instantiating them first.
433 if (prototype.#isInterceptorClass &&
434 constructor.prototype.#deferredAction) {
435 finishAddStubsHelper(constructor.prototype);
436 }
437 }
438
439 #trivialNsmHandlers;
440
441 var properties = Object.keys(processedClasses.pending);
442 for (var i = 0; i < properties.length; i++) finishClass(properties[i]);
443 }
444
445
446 // For convenience, this method can be called with a prototype as argument
447 // or, if it was bound to an object, by invoking it as a method. Therefore,
448 // if prototype is undefined, this is used as prototype.
449 function finishAddStubsHelper(prototype) {
450 var prototype = prototype || this;
451 var object;
452 while (prototype.#deferredAction != #markerFun) {
453 if (prototype.hasOwnProperty(#deferredActionString)) {
454 delete prototype.#deferredAction; // Intended to make it slow, too.
455 var properties = Object.keys(prototype);
456 for (var index = 0; index < properties.length; index++) {
457 var property = properties[index];
458 var firstChar = property.charCodeAt(0);
459 var elem;
460 // We have to filter out some special properties that are used for
461 // metadata in descriptors. Currently, we filter everything that
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 }
474 convertToFastObject(prototype);
475 }
476 prototype = prototype.__proto__;
477 }
478 }
479
480 function processClassData(cls, descriptor, processedClasses) {
481 descriptor = convertToSlowObject(descriptor); // Use a slow object.
482 var previousProperty;
483 var properties = Object.keys(descriptor);
484 var hasDeferredWork = false;
485 var shouldDeferWork =
486 supportsDirectProtoAccess && cls != #objectClassName;
487 for (var i = 0; i < properties.length; i++) {
488 var property = properties[i];
489 var firstChar = property.charCodeAt(0);
490 if (property === "static") {
491 processStatics(#statics[cls] = descriptor.static,
492 processedClasses);
493 delete descriptor.static;
494 } else if (firstChar === 43) { // 43 is "+".
495 mangledNames[previousProperty] = property.substring(1);
496 var flag = descriptor[property];
497 if (flag > 0)
498 descriptor[previousProperty].$reflectableField = flag;
499 } else if (firstChar === 42) { // 42 is "*"
500 descriptor[previousProperty].$defaultValuesField =
501 descriptor[property];
502 var optionalMethods = descriptor.$methodsWithOptionalArgumentsField;
503 if (!optionalMethods) {
504 descriptor.$methodsWithOptionalArgumentsField = optionalMethods={}
505 }
506 optionalMethods[property] = previousProperty;
507 } else {
508 var elem = descriptor[property];
509 if (property !== "${namer.classDescriptorProperty}" &&
510 elem != null &&
511 elem.constructor === Array &&
512 property !== "<>") {
513 if (shouldDeferWork) {
514 hasDeferredWork = true;
515 } else {
516 addStubs(descriptor, elem, property, false, []);
517 }
518 } else {
519 previousProperty = property;
520 }
521 }
522 }
523
524 if (hasDeferredWork)
525 descriptor.#deferredAction = finishAddStubsHelper;
526
527 /* The 'fields' are either a constructor function or a
528 * string encoding fields, constructor and superclass. Gets the
529 * superclass and fields in the format
530 * 'Super;field1,field2'
531 * from the CLASS_DESCRIPTOR_PROPERTY property on the descriptor.
532 */
533 var classData = descriptor["${namer.classDescriptorProperty}"],
534 split, supr, fields = classData;
535
536 if (#hasRetainedMetadata)
537 if (typeof classData == "object" &&
538 classData instanceof Array) {
539 classData = fields = classData[0];
540 }
541 // ${ClassBuilder.fieldEncodingDescription}.
542 var s = fields.split(";");
543 fields = s[1] == "" ? [] : s[1].split(",");
544 supr = s[0];
545 // ${ClassBuilder.functionTypeEncodingDescription}.
546 split = supr.split(":");
547 if (split.length == 2) {
548 supr = split[0];
549 var functionSignature = split[1];
550 if (functionSignature)
551 descriptor.${namer.operatorSignature} = function(s) {
552 return function() {
553 return #types[s];
554 };
555 }(functionSignature);
556 }
557
558 if (supr) processedClasses.pending[cls] = supr;
559 if (#notInCspMode) {
560 processedClasses.combinedConstructorFunction +=
561 defineClass(cls, fields);
562 processedClasses.constructorsList.push(cls);
563 }
564 processedClasses.collected[cls] = [globalObject, descriptor];
565 classes.push(cls);
566 }
567 }
568
569 function processStatics(descriptor, processedClasses) {
570 var properties = Object.keys(descriptor);
571 for (var i = 0; i < properties.length; i++) {
572 var property = properties[i];
573 if (property === "${namer.classDescriptorProperty}") continue;
574 var element = descriptor[property];
575 var firstChar = property.charCodeAt(0);
576 var previousProperty;
577 if (firstChar === 43) { // 43 is "+".
578 mangledGlobalNames[previousProperty] = property.substring(1);
579 var flag = descriptor[property];
580 if (flag > 0)
581 descriptor[previousProperty].$reflectableField = flag;
582 if (element && element.length)
583 #typeInformation[previousProperty] = element;
584 } else if (firstChar === 42) { // 42 is "*"
585 globalObject[previousProperty].$defaultValuesField = element;
586 var optionalMethods = descriptor.$methodsWithOptionalArgumentsField;
587 if (!optionalMethods) {
588 descriptor.$methodsWithOptionalArgumentsField = optionalMethods = {}
589 }
590 optionalMethods[property] = previousProperty;
591 } else if (typeof element === "function") {
592 globalObject[previousProperty = property] = element;
593 functions.push(property);
594 #globalFunctions[property] = element;
595 } else if (element.constructor === Array) {
596 if (#needsStructuredMemberInfo) {
597 addStubs(globalObject, element, property, true, functions);
598 }
599 } else {
600 // We will not enter this case if no classes are defined.
601 if (#needsClassSupport) {
602 previousProperty = property;
603 processClassData(property, element, processedClasses);
604 }
605 }
606 }
607 }
608
609 if (#needsStructuredMemberInfo) {
610
611 // See [dart2js.js_emitter.ContainerBuilder.addMemberMethod] for format of
612 // [array].
613
614 // Processes the stub declaration given by [array] and stores the results
615 // in the corresponding [prototype]. [name] is the property name in
616 // [prototype] that the stub declaration belongs to.
617 // If [isStatic] is true, the property being processed belongs to a static
618 // function and thus is stored as a global. In that case we also add all
619 // generated functions to the [functions] array, which is used by the
620 // mirrors system to enumerate all static functions of a library. For
621 // non-static functions we might still add some functions to [functions] but
622 // the information is thrown away at the call site. This is to avoid
623 // conditionals.
624 function addStubs(prototype, array, name, isStatic, functions) {
625 var index = $FUNCTION_INDEX, alias = array[index], f;
626 if (typeof alias == "string") {
627 f = array[++index];
628 } else {
629 f = alias;
630 alias = name;
631 }
632 var funcs = [prototype[name] = prototype[alias] = f];
633 f.\$stubName = name;
634 functions.push(name);
635 for (; index < array.length; index += 2) {
636 f = array[index + 1];
637 if (typeof f != "function") break;
638 f.\$stubName = ${readString("array", "index + 2")};
639 funcs.push(f);
640 if (f.\$stubName) {
641 prototype[f.\$stubName] = f;
642 functions.push(f.\$stubName);
643 }
644 }
645 index++;
646 for (var i = 0; i < funcs.length; index++, i++) {
647 funcs[i].\$callName = ${readString("array", "index")};
648 }
649 var getterStubName = ${readString("array", "index")};
650 array = array.slice(++index);
651 var requiredParameterInfo = ${readInt("array", "0")};
652 var requiredParameterCount = requiredParameterInfo >> 1;
653 var isAccessor = (requiredParameterInfo & 1) === 1;
654 var isSetter = requiredParameterInfo === 3;
655 var isGetter = requiredParameterInfo === 1;
656 var optionalParameterInfo = ${readInt("array", "1")};
657 var optionalParameterCount = optionalParameterInfo >> 1;
658 var optionalParametersAreNamed = (optionalParameterInfo & 1) === 1;
659 var isIntercepted =
660 requiredParameterCount + optionalParameterCount != funcs[0].length;
661 var functionTypeIndex = ${readFunctionType("array", "2")};
662 var unmangledNameIndex = $unmangledNameIndex;
663
664 if (getterStubName) {
665 f = tearOff(funcs, array, isStatic, name, isIntercepted);
666 prototype[name].\$getter = f;
667 f.\$getterStub = true;
668 // Used to create an isolate using spawnFunction.
669 if (isStatic) {
670 #globalFunctions[name] = f;
671 functions.push(getterStubName);
672 }
673 prototype[getterStubName] = f;
674 funcs.push(f);
675 f.\$stubName = getterStubName;
676 f.\$callName = null;
677 // Update the interceptedNames map (which only exists if `invokeOn` was
678 // enabled).
679 if (#enabledInvokeOn)
680 if (isIntercepted) #interceptedNames[getterStubName] = 1;
681 }
682
683 if (#usesMangledNames) {
684 var isReflectable = array.length > unmangledNameIndex;
685 if (isReflectable) {
686 for (var i = 0; i < funcs.length; i++) {
687 funcs[i].$reflectableField = 1;
688 funcs[i].$reflectionInfoField = array;
689 }
690 var mangledNames = isStatic ? #mangledGlobalNames : #mangledNames;
691 var unmangledName = ${readString("array", "unmangledNameIndex")};
692 // The function is either a getter, a setter, or a method.
693 // If it is a method, it might also have a tear-off closure.
694 // The unmangledName is the same as the getter-name.
695 var reflectionName = unmangledName;
696 if (getterStubName) mangledNames[getterStubName] = reflectionName;
697 if (isSetter) {
698 reflectionName += "=";
699 } else if (!isGetter) {
700 reflectionName += ":" + requiredParameterCount +
701 ":" + optionalParameterCount;
702 }
703 mangledNames[name] = reflectionName;
704 funcs[0].$reflectionNameField = reflectionName;
705 funcs[0].$metadataIndexField = unmangledNameIndex + 1;
706 if (optionalParameterCount) prototype[unmangledName + "*"] = funcs[0];
707 }
708 }
709 }
710
711 #tearOffCode;
712 }
713
714 if (#hasIncrementalSupport) {
715 #incrementalHelper.addStubs = addStubs;
716 }
717
718 var functionCounter = 0;
719 if (!#libraries) #libraries = [];
720 if (!#mangledNames) #mangledNames = map();
721 if (!#mangledGlobalNames) #mangledGlobalNames = map();
722 if (!#statics) #statics = map();
723 if (!#typeInformation) #typeInformation = map();
724 if (!#globalFunctions) #globalFunctions = map();
725 if (#enabledInvokeOn)
726 if (!#interceptedNames) #interceptedNames = #interceptedNamesSet;
727 var libraries = #libraries;
728 var mangledNames = #mangledNames;
729 var mangledGlobalNames = #mangledGlobalNames;
730 var hasOwnProperty = Object.prototype.hasOwnProperty;
731 var length = programData.length;
732 var processedClasses = map();
733 processedClasses.collected = map();
734 processedClasses.pending = map();
735 if (#notInCspMode) {
736 processedClasses.constructorsList = [];
737 // For every class processed [processedClasses.combinedConstructorFunction]
738 // will be updated with the corresponding constructor function.
739 processedClasses.combinedConstructorFunction =
740 "function \$reflectable(fn){fn.$reflectableField=1;return fn};\\n"+
741 "var \$desc;\\n";
742 }
743 for (var i = 0; i < length; i++) {
744 var data = programData[i];
745
746 // [data] contains these elements:
747 // 0. The library name (not unique).
748 // 1. The library URI (unique).
749 // 2. A function returning the metadata associated with this library.
750 // 3. The global object to use for this library.
751 // 4. An object literal listing the members of the library.
752 // 5. This element is optional and if present it is true and signals that this
753 // library is the root library (see dart:mirrors IsolateMirror.rootLibrary).
754 //
755 // The entries of [data] are built in [assembleProgram] above.
756
757 var name = data[0];
758 var uri = data[1];
759 var metadata = data[2];
760 var globalObject = data[3];
761 var descriptor = data[4];
762 var isRoot = !!data[5];
763 var fields = descriptor && descriptor["${namer.classDescriptorProperty}"];
764 if (fields instanceof Array) fields = fields[0];
765 var classes = [];
766 var functions = [];
767 processStatics(descriptor, processedClasses);
768 libraries.push([name, uri, classes, functions, metadata, fields, isRoot,
769 globalObject]);
770 }
771 if (#needsClassSupport) finishClasses(processedClasses);
772 }''';
773
774 // TODO(zarah): Remove empty else branches in output when if(#hole) is false.
775 return js.statement(skeleton, holes);
776 }
777
778 String readString(String array, String index) {
779 return readChecked(
780 array, index, 'result != null && typeof result != "string"', 'string');
781 }
782
783 String readInt(String array, String index) {
784 return readChecked(
785 array, index,
786 'result != null && (typeof result != "number" || (result|0) !== result)',
787 'int');
788 }
789
790 String readFunctionType(String array, String index) {
791 return readChecked(
792 array, index,
793 'result != null && '
794 '(typeof result != "number" || (result|0) !== result) && '
795 'typeof result != "function"',
796 'function or int');
797 }
798
799 String readChecked(String array, String index, String check, String type) {
800 if (!VALIDATE_DATA) return '$array[$index]';
801 return '''
802 (function() {
803 var result = $array[$index];
804 if ($check) {
805 throw new Error(
806 name + ": expected value of type \'$type\' at index " + ($index) +
807 " but got " + (typeof result));
808 }
809 return result;
810 })()''';
811 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/js_emitter/old_emitter/reflection_data_parser.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698