blob: 8b868829fd7e7646a92afea6f4ee7bcc06be2b87 [file] [log] [blame]
// Copyright (c) 2013, 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.
// @dart = 2.9
library test.proxy_type;
import 'dart:mirrors';
import 'package:expect/expect.dart';
// This test is much longer that is strictly necessary to test
// InstanceMirror.type in the face of a reflectee overriding runtimeType, but
// shows a case where one might have legimate reason to override runtimeType.
// See section 2.2 in Mark Miller's Robust Composition: Towards a Unified
// Approach to Access Control and Concurrency Control.
class Alice {
Bob bob = new Bob();
Carol carol = new Carol();
sayFooUnattenuated() {;
sayFooAttenuated() {
bool enabled = true;
bool gate() => enabled; CarolCaretaker(carol, gate));
enabled = false; // Attenuate a capability
sayBar() {;
class Bob {
Carol savedCarol;
foo(Carol carol) {
savedCarol = carol; // Store a capability;
bar() {;
class Carol {
foo() => 'c';
typedef bool Gate();
class CarolCaretaker implements Carol {
final Carol _carol;
final Gate _gate;
CarolCaretaker(this._carol, this._gate);
foo() {
if (!_gate()) throw new NoSuchMethodError(this, #foo, [], {});
Type get runtimeType => Carol;
main() {
Alice alice1 = new Alice();
alice1.sayBar(); // Bob still has authority to use Carol
Alice alice2 = new Alice();
Expect.throwsNoSuchMethodError(() => alice2.sayBar(),
'Authority should have been attenuated');
// At the base level, a caretaker for a Carol masquerades as a Carol.
CarolCaretaker caretaker = new CarolCaretaker(new Carol(), () => true);
Expect.isTrue(caretaker is Carol);
Expect.equals(Carol, caretaker.runtimeType);
// At the reflective level, the caretaker is distinguishable.
Expect.equals(reflectClass(CarolCaretaker), reflect(caretaker).type);