This repository has been archived by the owner on Feb 22, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
0c17586
commit b5ef7f4
Showing
11 changed files
with
433 additions
and
152 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,199 @@ | ||
// Copyright (c) 2014, 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 js.transformer.dart_initializer_generator; | ||
|
||
import 'package:js/src/js_elements.dart'; | ||
import 'package:logging/logging.dart'; | ||
import 'package:quiver/iterables.dart'; | ||
|
||
final _logger = new Logger('js.transformer.dart_initializer_generator'); | ||
|
||
const JS_PREFIX = '__package_js_impl__'; | ||
const JS_THIS_REF = '__js_this_ref__'; | ||
|
||
class DartInitializerGenerator { | ||
final String libraryName; | ||
final String libraryPath; | ||
final JsElements jsElements; | ||
|
||
final buffer = new StringBuffer(); | ||
|
||
DartInitializerGenerator(this.libraryName, this.libraryPath, this.jsElements); | ||
|
||
/** | ||
* Returns the transformed source. | ||
*/ | ||
String generate() { | ||
buffer.write( | ||
''' | ||
library ${libraryName}__init_js__; | ||
import 'dart:js' as js; | ||
import '${libraryPath}'; | ||
import 'package:js/src/js_impl.dart' as $JS_PREFIX; | ||
final _obj = js.context['Object']; | ||
initializeJavaScriptLibrary() { | ||
'''); | ||
|
||
jsElements.proxies.forEach((Proxy proxy) { | ||
if (proxy.constructor == null) return; | ||
var name = proxy.name; | ||
buffer.writeln(" $JS_PREFIX.registerFactoryForJsConstructor(" | ||
"$JS_PREFIX.context['${proxy.constructor}'], " | ||
"($JS_PREFIX.JsObject o) => new $name.created(o));"); | ||
}); | ||
|
||
buffer.writeln(" var lib = $JS_PREFIX.context['dart'];"); | ||
|
||
jsElements.exportedLibraries.values.forEach(_generateLibraryExportCall); | ||
|
||
buffer.writeln('}'); | ||
|
||
jsElements.exportedLibraries.values.forEach(_generateLibraryExportMethod); | ||
|
||
return buffer.toString(); | ||
} | ||
|
||
_generateLibraryExportCall(ExportedLibrary library) { | ||
buffer.writeln(" _export_${library.getPath('_')}(lib);"); | ||
} | ||
|
||
_generateLibraryExportMethod(ExportedLibrary library) { | ||
buffer.writeln( | ||
''' | ||
void _export_${library.getPath('_')}($JS_PREFIX.JsObject parent) { | ||
js.JsObject lib = parent['${library.name}']; | ||
'''); | ||
|
||
library.declarations.values.forEach(_generateDeclarationExportCall); | ||
library.children.values.forEach(_generateLibraryExportCall); | ||
|
||
buffer.writeln('}'); | ||
|
||
library.children.values.forEach(_generateLibraryExportMethod); | ||
library.declarations.values.forEach(_generateDeclarationExport); | ||
} | ||
|
||
void _generateDeclarationExportCall(ExportedElement element) { | ||
if (element is ExportedClass) { | ||
buffer.writeln(" _export_${element.getPath('_')}(lib);"); | ||
} | ||
} | ||
|
||
void _generateDeclarationExport(ExportedElement element) { | ||
if (element is ExportedClass) { | ||
_generateClass(element); | ||
} | ||
} | ||
|
||
void _generateClass(ExportedClass c) { | ||
buffer.writeln( | ||
''' | ||
void _export_${c.getPath('_')}($JS_PREFIX.JsObject parent) { | ||
var constructor = parent['${c.name}']; | ||
$JS_PREFIX.registerJsConstructorForType(${c.name}, constructor['_wrapDartObject']); | ||
var prototype = constructor['prototype']; | ||
'''); | ||
|
||
c.children.values.forEach(_generateClassMember); | ||
|
||
buffer.writeln("}"); | ||
} | ||
|
||
void _generateClassMember(ExportedElement e) { | ||
if (e is ExportedConstructor) { | ||
_generateConstructor(e); | ||
} else if (e is ExportedMethod) { | ||
_generateMethod(e); | ||
} else if (e is ExportedField) { | ||
_generateField(e); | ||
} | ||
} | ||
|
||
void _generateConstructor(ExportedConstructor c) { | ||
var constructorName = c.name == '' ? '_new' : '_new_${c.name}'; | ||
var dartParameters = _getDartParameters(c.parameters); | ||
var jsParameters = _getJsParameters(c.parameters); | ||
var namedPart = c.name == '' ? '' : '.${c.name}'; | ||
buffer.writeln(" constructor['$constructorName'] = ($jsParameters) => " | ||
"new ${c.parent.name}$namedPart($dartParameters);"); | ||
} | ||
|
||
void _generateMethod(ExportedMethod c) { | ||
var dartParameters = _getDartParameters(c.parameters); | ||
var jsParameters = _getJsParameters(c.parameters, withThis: true); | ||
buffer.write( | ||
''' | ||
// method ${c.name} | ||
prototype['${c.name}'] = new js.JsFunction.withThis(($jsParameters) { | ||
return $JS_THIS_REF.${c.name}($dartParameters); | ||
}); | ||
'''); | ||
} | ||
|
||
void _generateField(ExportedField f) { | ||
var name = f.name; | ||
var className = f.parent.name; | ||
buffer.write( | ||
''' | ||
// field $name | ||
_obj.callMethod('defineProperty', [prototype, '$name', | ||
new js.JsObject.jsify({ | ||
'get': new js.JsFunction.withThis((o) => (o[$JS_PREFIX.DART_OBJECT_PROPERTY] as $className).$name), | ||
'set': new js.JsFunction.withThis((o, v) => (o[$JS_PREFIX.DART_OBJECT_PROPERTY] as $className).$name = v), | ||
})]); | ||
'''); | ||
} | ||
|
||
|
||
String _getJsParameters(List<ExportedParameter> parameters, | ||
{bool withThis: false}) { | ||
var requiredParameters = parameters | ||
.where((p) => p.kind == ParameterKind.REQUIRED) | ||
.map((p) => p.name); | ||
var positionalParameters = parameters | ||
.where((p) => p.kind == ParameterKind.POSITIONAL) | ||
.map((p) => p.name); | ||
var namedParameters = parameters | ||
.where((p) => p.kind == ParameterKind.NAMED) | ||
.map((p) => p.name); | ||
var jsParameterList = withThis ? [JS_THIS_REF] : []; | ||
jsParameterList.addAll(requiredParameters); | ||
var jsParameters = jsParameterList.join(', '); | ||
if (positionalParameters.isNotEmpty) { | ||
jsParameters += ', [' + positionalParameters.join(', ') + ']'; | ||
} else if (namedParameters.isNotEmpty) { | ||
jsParameters += ', [__js_named_parameters_map__]'; | ||
} | ||
return jsParameters; | ||
} | ||
|
||
String _getDartParameters(List<ExportedParameter> parameters) { | ||
var requiredParameters = parameters | ||
.where((p) => p.kind == ParameterKind.REQUIRED) | ||
.map((p) => p.name); | ||
var positionalParameters = parameters | ||
.where((p) => p.kind == ParameterKind.POSITIONAL) | ||
.map((p) => p.name); | ||
var namedParameters = parameters | ||
.where((p) => p.kind == ParameterKind.NAMED) | ||
.map((p) => p.name); | ||
var dartNamedParameters = namedParameters.map((name) => | ||
"${name}: _getOptionalArg(__js_named_parameters_map__, '${name}')"); | ||
var dartParameters = concat([ | ||
requiredParameters, | ||
positionalParameters, | ||
dartNamedParameters]) | ||
.join(', '); | ||
|
||
return dartParameters; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.