Chromium Code Reviews| Index: sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart |
| diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart b/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart |
| index e7eb3ce1eb92696f13a5652c252591e0ddb73983..03b0f87fc1cf6e0993d9011679d506b8b2196f94 100644 |
| --- a/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart |
| +++ b/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart |
| @@ -287,6 +287,7 @@ class CodeEmitterTask extends CompilerTask { |
| static const RANGE2_LAST = 0x7e; |
| static const RANGE3_FIRST = 0x25; // %&'()*+ encodes 10..16 |
| static const RANGE3_LAST = 0x2b; |
| + static const REFLECTION_MARKER = 0x2d; |
| jsAst.FunctionDeclaration get generateAccessorFunction { |
| const RANGE1_SIZE = RANGE1_LAST - RANGE1_FIRST + 1; |
| @@ -303,6 +304,13 @@ class CodeEmitterTask extends CompilerTask { |
| jsAst.Fun fun = js.fun(['field', 'prototype'], [ |
| js('var len = field.length'), |
| js('var code = field.charCodeAt(len - 1)'), |
| + js('var reflectable = false'), |
| + js.if_('code == $REFLECTION_MARKER', [ |
| + js('len--'), |
| + js('code = field.charCodeAt(len - 1)'), |
| + js('field = field.substring(0, len)'), |
| + js('reflectable = true') |
| + ]), |
| js('code = ((code >= $RANGE1_FIRST) && (code <= $RANGE1_LAST))' |
| ' ? code - $RANGE1_ADJUST' |
| ' : ((code >= $RANGE2_FIRST) && (code <= $RANGE2_LAST))' |
| @@ -329,7 +337,9 @@ class CodeEmitterTask extends CompilerTask { |
| js('var receiver = (getterCode & 1) ? "this" : "$receiverParamName"'), |
| js('var body = "return " + receiver + "." + field'), |
| js('prototype["${namer.getterPrefix}" + accessorName] = ' |
| - 'new Function(args, body)') |
| + 'new Function(args, body)'), |
| + js('prototype["${namer.getterPrefix}" + accessorName].\$reflectable =' |
|
ngeoffray
2013/08/29 07:45:49
Please move $reflectable to the namer.
karlklose
2013/08/29 15:33:37
Done.
|
| + ' reflectable') |
|
ngeoffray
2013/08/29 07:45:49
Only add it if reflectable is true?
karlklose
2013/08/29 15:33:37
Done.
|
| ]), |
| // if (needsSetter) { |
| @@ -340,7 +350,9 @@ class CodeEmitterTask extends CompilerTask { |
| js('var receiver = (setterCode & 1) ? "this" : "$receiverParamName"'), |
| js('var body = receiver + "." + field + "$_=$_$valueParamName"'), |
| js('prototype["${namer.setterPrefix}" + accessorName] = ' |
| - 'new Function(args, body)') |
| + 'new Function(args, body)'), |
| + js('prototype["${namer.setterPrefix}" + accessorName].\$reflectable =' |
| + ' reflectable') |
|
ngeoffray
2013/08/29 07:45:49
ditto.
karlklose
2013/08/29 15:33:37
Done.
|
| ]), |
| ]), |
| @@ -1099,7 +1111,9 @@ class CodeEmitterTask extends CompilerTask { |
| String reflectionName = getReflectionName(selector, invocationName); |
| if (reflectionName != null) { |
| - defineStub('+$reflectionName', js('0')); |
| + var reflectable = |
| + js(backend.isAccessibleByReflection(member) ? '1' : '0'); |
| + defineStub('+$reflectionName', reflectable); |
| } |
| } |
| @@ -1270,7 +1284,9 @@ class CodeEmitterTask extends CompilerTask { |
| builder.addProperty(name, code); |
| String reflectionName = getReflectionName(member, name); |
| if (reflectionName != null) { |
| - builder.addProperty('+$reflectionName', js('0')); |
| + var reflectable = |
| + js(backend.isAccessibleByReflection(member) ? '1' : '0'); |
| + builder.addProperty('+$reflectionName', reflectable); |
| } |
| code = backend.generatedBailoutCode[member]; |
| if (code != null) { |
| @@ -1325,7 +1341,10 @@ class CodeEmitterTask extends CompilerTask { |
| String getter = '${namer.getterPrefix}$base'; |
| mangledFieldNames[getter] = name; |
| recordedMangledNames.add(getter); |
| - return null; |
| + // TODO(karlklose,ahe): we do not actually need to store information |
| + // about the name of this setter in the output, but it is needed for |
| + // marking the function as invokable by reflection. |
| + return '$name='; |
| } |
| if (elementOrSelector is Selector |
| || elementOrSelector.isFunction() |
| @@ -1861,6 +1880,9 @@ class CodeEmitterTask extends CompilerTask { |
| buffer.write(FIELD_CODE_CHARACTERS[code - FIRST_FIELD_CODE]); |
| } |
| } |
| + if (backend.isAccessibleByReflection(field)) { |
| + buffer.write(new String.fromCharCode(REFLECTION_MARKER)); |
| + } |
| } |
| }); |
| } |
| @@ -2300,7 +2322,8 @@ class CodeEmitterTask extends CompilerTask { |
| emitStaticFunction(buffer, name, code); |
| String reflectionName = getReflectionName(element, name); |
| if (reflectionName != null) { |
| - buffer.write(',$n$n"+$reflectionName":${_}0'); |
| + var reflectable = backend.isAccessibleByReflection(element) ? 1 : 0; |
| + buffer.write(',$n$n"+$reflectionName":${_}$reflectable'); |
| } |
| jsAst.Expression bailoutCode = backend.generatedBailoutCode[element]; |
| if (bailoutCode != null) { |
| @@ -4078,7 +4101,9 @@ class CodeEmitterTask extends CompilerTask { |
| var previousProperty; |
| if (firstChar === "+") { |
| mangledGlobalNames[previousProperty] = property.substring(1); |
| - if (element && element.length) ''' // Breaking long line. |
| + descriptor[previousProperty].\$reflectable = ''' // Break long line. |
| +'''(descriptor[property] == 1); |
| + if (element && element.length) ''' // Break long line. |
| '''init.interfaces[previousProperty] = element; |
| } else if (firstChar === "@") { |
| property = property.substring(1); |
| @@ -4097,6 +4122,8 @@ class CodeEmitterTask extends CompilerTask { |
| processStatics(init.statics[property] = element[prop]); |
| } else if (firstChar === "+") { |
| mangledNames[previousProp] = prop.substring(1); |
| + element[previousProp].\$reflectable = ''' // Break long line. |
| +'''(element[prop] == 1); |
| } else if (firstChar === "@" && prop !== "@") { |
| newDesc[prop.substring(1)][$metadataField] = element[prop]; |
| } else { |