Является ли поведение зеркала Dart, запрещающим вызов частных методов из других библиотек, гарантированным и частью спецификации?

если у меня есть 2 файла:

бин.дротик:

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

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

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

библиотека дартс:

library lib;

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

Если я запускаю bin.dart, я получаю то, на что надеюсь, исключение при попытке вызвать закрытый метод. но если я закомментирую строку import 'lib.dart' и раскомментирую локальное определение Foo на этот раз, оно запустится без исключения, что, я полагаю, нормально, потому что теперь частный метод вызывается из объявляющей библиотеки. Итак, мой вопрос: гарантировано ли поведение? Мне нужно убедиться, что точка вызова через зеркала в моей библиотеке не позволит вызывать частные члены из других библиотек, в настоящее время я явно проверяю это, выполняя проверку имен, начинающихся с _:

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

однако, если конфиденциальность по-прежнему соблюдается даже зеркалами по умолчанию, я могу избавиться от этой проверки и удалить импорт для dart:mirrors в моей библиотеке, спасибо.

ОБНОВИТЬ

Что, если бы символ inv.method гарантированно всегда производился из:

inv.method = MirrorSystem.getSymbol(stringName);

это предотвратит вызов частного метода, как в файле dart:mirrors-patch_mirrors_patch.dart строка 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);
  }

сделает тест, чтобы проверить, что он не начинается с подчеркивания, поэтому предотвратит создание каких-либо частных символов, если вы можете гарантировать, что все символы генерируются таким образом?


person Daniel Robinson    schedule 09.11.2014    source источник


Ответы (2)


Reflection позволяет обойти все механизмы конфиденциальности. Так что нет, на него нельзя положиться. Думайте о «_foo» как о «foo» с префиксом библиотечного токена, который пользователи не могут генерировать. Таким образом, #_bar в основной библиотеке отличается от #_bar в библиотеке lib. Однако вы можете просто перечислить все идентификаторы данного объекта foo и найти приватную функцию.

Если вам нужна настоящая конфиденциальность, вам нужно использовать изоляты.

person Florian Loitsch    schedule 09.11.2014

Вы можете получить частный символ, перебирая ключи ClassMirror.instanceMembers или ClassMirror.staticMembers. Так что нет, вы не можете предотвратить создание частных символов.

person Peter von der Ahé    schedule 19.11.2014