mirror of
https://github.com/dart-lang/sdk
synced 2024-10-03 02:42:05 +00:00
Include field reference with implicit getter / setter functions
- When printing implicit getter or setter functions, include the field that the implicit functions were generated for. - Display field on function view in Observatory. - Service unit test. R=rmacnak@google.com Review URL: https://codereview.chromium.org/1440753002 .
This commit is contained in:
parent
31b1288f06
commit
c6a8c44eae
|
@ -46,6 +46,14 @@
|
|||
<any-service-ref ref="{{ function.dartOwner }}"></any-service-ref>
|
||||
</div>
|
||||
</div>
|
||||
<template if="{{ function.field != null }}">
|
||||
<div class="memberItem">
|
||||
<div class="memberName">field</div>
|
||||
<div class="memberValue">
|
||||
<any-service-ref ref="{{ function.field }}"></any-service-ref>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div class="memberItem">
|
||||
<div class="memberName">script</div>
|
||||
<div class="memberValue">
|
||||
|
|
|
@ -2575,6 +2575,7 @@ class ServiceFunction extends HeapObject with Coverage {
|
|||
@observable bool isDart;
|
||||
@observable ProfileFunction profile;
|
||||
@observable Instance icDataArray;
|
||||
@observable Field field;
|
||||
|
||||
bool get canCache => true;
|
||||
bool get immutable => false;
|
||||
|
@ -2622,6 +2623,7 @@ class ServiceFunction extends HeapObject with Coverage {
|
|||
deoptimizations = map['_deoptimizations'];
|
||||
usageCounter = map['_usageCounter'];
|
||||
icDataArray = map['_icDataArray'];
|
||||
field = map['_field'];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
library implicit_getter_setter_test;
|
||||
|
||||
import 'package:observatory/service_io.dart';
|
||||
import 'package:unittest/unittest.dart';
|
||||
import 'test_helper.dart';
|
||||
|
||||
class A {
|
||||
double field = 0.0;
|
||||
}
|
||||
|
||||
script() {
|
||||
for (int i = 0; i < 10; i++) {
|
||||
new A();
|
||||
}
|
||||
}
|
||||
|
||||
testGetter(Isolate isolate) async {
|
||||
Library rootLibrary = await isolate.rootLibrary.load();
|
||||
expect(rootLibrary.classes.length, equals(1));
|
||||
Class classA = await rootLibrary.classes[0].load();
|
||||
expect(classA.name, equals('A'));
|
||||
// Find getter.
|
||||
ServiceFunction getterFunc;
|
||||
for (ServiceFunction function in classA.functions) {
|
||||
if (function.name == 'field') {
|
||||
getterFunc = function;
|
||||
break;
|
||||
}
|
||||
}
|
||||
expect(getterFunc, isNotNull);
|
||||
await getterFunc.load();
|
||||
Field field = await getterFunc.field.load();
|
||||
expect(field, isNotNull);
|
||||
expect(field.name, equals('field'));
|
||||
Class classDouble = await field.guardClass.load();
|
||||
expect(classDouble.name, equals('_Double'));
|
||||
}
|
||||
|
||||
|
||||
testSetter(Isolate isolate) async {
|
||||
Library rootLibrary = await isolate.rootLibrary.load();
|
||||
expect(rootLibrary.classes.length, equals(1));
|
||||
Class classA = await rootLibrary.classes[0].load();
|
||||
expect(classA.name, equals('A'));
|
||||
// Find setter.
|
||||
ServiceFunction setterFunc;
|
||||
for (ServiceFunction function in classA.functions) {
|
||||
if (function.name == 'field=') {
|
||||
setterFunc = function;
|
||||
break;
|
||||
}
|
||||
}
|
||||
expect(setterFunc, isNotNull);
|
||||
await setterFunc.load();
|
||||
Field field = await setterFunc.field.load();
|
||||
expect(field, isNotNull);
|
||||
expect(field.name, equals('field'));
|
||||
Class classDouble = await field.guardClass.load();
|
||||
expect(classDouble.name, equals('_Double'));
|
||||
}
|
||||
|
||||
|
||||
var tests = [testGetter, testSetter];
|
||||
|
||||
main(args) => runIsolateTests(args, tests, testeeBefore: script);
|
|
@ -5516,6 +5516,27 @@ void Function::set_saved_args_desc(const Array& value) const {
|
|||
}
|
||||
|
||||
|
||||
RawField* Function::LookupImplicitGetterSetterField() const {
|
||||
ASSERT((kind() == RawFunction::kImplicitGetter) ||
|
||||
(kind() == RawFunction::kImplicitSetter) ||
|
||||
(kind() == RawFunction::kImplicitStaticFinalGetter));
|
||||
const Class& owner = Class::Handle(Owner());
|
||||
ASSERT(!owner.IsNull());
|
||||
const Array& fields = Array::Handle(owner.fields());
|
||||
ASSERT(!fields.IsNull());
|
||||
Field& field = Field::Handle();
|
||||
for (intptr_t i = 0; i < fields.Length(); i++) {
|
||||
field ^= fields.At(i);
|
||||
ASSERT(!field.IsNull());
|
||||
if (field.token_pos() == token_pos()) {
|
||||
return field.raw();
|
||||
}
|
||||
}
|
||||
return Field::null();
|
||||
}
|
||||
|
||||
|
||||
|
||||
RawFunction* Function::parent_function() const {
|
||||
if (IsClosureFunction()) {
|
||||
const Object& obj = Object::Handle(raw_ptr()->data_);
|
||||
|
@ -7272,6 +7293,14 @@ void Function::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
|||
jsobj.AddProperty("_optimizedCallSiteCount", optimized_call_site_count());
|
||||
jsobj.AddProperty("_deoptimizations",
|
||||
static_cast<intptr_t>(deoptimization_counter()));
|
||||
if ((kind() == RawFunction::kImplicitGetter) ||
|
||||
(kind() == RawFunction::kImplicitSetter) ||
|
||||
(kind() == RawFunction::kImplicitStaticFinalGetter)) {
|
||||
const Field& field = Field::Handle(LookupImplicitGetterSetterField());
|
||||
if (!field.IsNull()) {
|
||||
jsobj.AddProperty("_field", field);
|
||||
}
|
||||
}
|
||||
|
||||
const Script& script = Script::Handle(this->script());
|
||||
if (!script.IsNull()) {
|
||||
|
|
|
@ -2197,6 +2197,8 @@ class Function : public Object {
|
|||
RawContextScope* context_scope() const;
|
||||
void set_context_scope(const ContextScope& value) const;
|
||||
|
||||
RawField* LookupImplicitGetterSetterField() const;
|
||||
|
||||
// Enclosing function of this local function.
|
||||
RawFunction* parent_function() const;
|
||||
|
||||
|
|
Loading…
Reference in a new issue