Daniel Robinson
Daniel Robinson

Reputation: 14888

Is Dart mirror behavior to not allow invocation of private methods from other libraries guaranteed and part of the spec?

if I have 2 files:

bin.dart:

import 'lib.dart';
import 'dart:mirrors';

/*
class Foo{
  bool _bar() => true;
}
*/

void main() {
  var foo = new Foo();
  print(reflect(foo).invoke(#_bar, []));
}

lib.dart:

library lib;

class Foo{
  bool _bar() => true;
}

If I run bin.dart I get what I hope to happen, an exception when trying to invoke a private method. but if I comment out the import 'lib.dart' line and uncomment the local Foo definition this timeit runs without exception, which I suppose is ok because now the private mthod is being invoked from the declaring library. So my question is, is the behavior guaranteed? I need to make sure that a point of invocation via mirrors in my library will not allow the invocation of private members from other libraries, presently I explicitly check this by doing a check for a names starting with _:

if(MirrorSystem.getName(inv.method).startsWith('_')){
  throw new RestrictedMethodError(inv.method);
}else{
  _this.invoke(inv.method, inv.posArgs, inv.namArgs);
}

however if the privacy is still respected even by mirrors by default then I can get rid of this check and remove the import for dart:mirrors in my library, thanks.

UPDATE

What if the symbol inv.method was guaranteed to always be derived from:

inv.method = MirrorSystem.getSymbol(stringName);

would this then prevent the private method from being called as in the file dart:mirrors-patch_mirrors_patch.dart line 92:

  static Symbol getSymbol(String name,[LibraryMirror library]) {
    if((library != null && library is !_LocalLibraryMirror) ||
       ((name.length > 0) && (name[0] == "_") && (library == null))) {
      throw new ArgumentError(library);
    }
    if (library != null) name = _mangleName(name, library._reflectee);
    return new _symbol_dev.Symbol.unvalidated(name);
  }

will do the test to check it doesn't start with underscore, so will prevent any "private symbols" from being generated if you can guarantee that all the symbols are being generated in this fashion?

Upvotes: 2

Views: 149

Answers (2)

You can obtain a private symbol by iterating the keys of ClassMirror.instanceMembers or ClassMirror.staticMembers. So no, you cannot prevent the creation of private symbols.

Upvotes: 0

Florian Loitsch
Florian Loitsch

Reputation: 8128

Reflection allows you to overcome all privacy mechanisms. So no, you can not rely on it. Think of "_foo" as "foo" prefixed by a library-token that users cannot generate. As such, #_bar in the main-library is different from #_bar in the lib library. However, you could just enumerate all identifiers of the given foo object and find the private function.

If you need real privacy you need to use isolates.

Upvotes: 5

Related Questions