How to print called functions in android? - frida

I'm using frida on an APK and I'm trying to print out which function is being called, and especially which parameters are sent to it. My environment is set correctly as I can print out classes, and perform various actions in accordance to the docs.
This is the closest i've found:
https://codeshare.frida.re/#razaina/get-a-stack-trace-in-your-hook/
But the code gives out errors (ThreadDef undefined and so on)
And the frida docs didn't help me get where I'm trying to.
Any guidance? suggestions? help?

The code from codeshare#razaina has bugs which can be easily fixed (threadef != ThreadDef)
var printBacktrace = function () {
Java.perform(function() {
var JLog = Java.use('android.util.Log'), JException = Java.use('java.lang.Exception');
// getting stacktrace by throwing an exception
console.warn(JLog.getStackTraceString(JException.$new()));
});
};
Just call printBacktrace() w/e you want to see who called your hooked function.
If you want to hook all the methods of Java class you can use this snippet;
var Color = {
RESET: "\x1b[39;49;00m", Black: "0;01", Blue: "4;01", Cyan: "6;01", Gray: "7;11", Green: "2;01", Purple: "5;01", Red: "1;01", Yellow: "3;01",
Light: {
Black: "0;11", Blue: "4;11", Cyan: "6;11", Gray: "7;01", Green: "2;11", Purple: "5;11", Red: "1;11", Yellow: "3;11"
}
};
/**
*
* #param input.
* If an object is passed it will print as json
* #param kwargs options map {
* -l level: string; log/warn/error
* -i indent: boolean; print JSON prettify
* -c color: #see ColorMap
* }
*/
var LOG = function (input, kwargs) {
kwargs = kwargs || {};
var logLevel = kwargs['l'] || 'log', colorPrefix = '\x1b[3', colorSuffix = 'm';
if (typeof input === 'object')
input = JSON.stringify(input, null, kwargs['i'] ? 2 : null);
if (kwargs['c'])
input = colorPrefix + kwargs['c'] + colorSuffix + input + Color.RESET;
console[logLevel](input);
};
var printBacktrace = function () {
Java.perform(function() {
var android_util_Log = Java.use('android.util.Log'), java_lang_Exception = Java.use('java.lang.Exception');
// getting stacktrace by throwing an exception
LOG(android_util_Log.getStackTraceString(java_lang_Exception.$new()), { c: Color.Gray });
});
};
function traceClass(targetClass) {
var hook;
try {
hook = Java.use(targetClass);
} catch (e) {
console.error("trace class failed", e);
return;
}
var methods = hook.class.getDeclaredMethods();
hook.$dispose();
var parsedMethods = [];
methods.forEach(function (method) {
var methodStr = method.toString();
var methodReplace = methodStr.replace(targetClass + ".", "TOKEN").match(/\sTOKEN(.*)\(/)[1];
parsedMethods.push(methodReplace);
});
uniqBy(parsedMethods, JSON.stringify).forEach(function (targetMethod) {
traceMethod(targetClass + '.' + targetMethod);
});
}
function traceMethod(targetClassMethod) {
var delim = targetClassMethod.lastIndexOf('.');
if (delim === -1)
return;
var targetClass = targetClassMethod.slice(0, delim);
var targetMethod = targetClassMethod.slice(delim + 1, targetClassMethod.length);
var hook = Java.use(targetClass);
var overloadCount = hook[targetMethod].overloads.length;
LOG({ tracing: targetClassMethod, overloaded: overloadCount }, { c: Color.Green });
for (var i = 0; i < overloadCount; i++) {
hook[targetMethod].overloads[i].implementation = function () {
var log = { '#': targetClassMethod, args: [] };
for (var j = 0; j < arguments.length; j++) {
var arg = arguments[j];
// quick&dirty fix for java.io.StringWriter char[].toString() impl because frida prints [object Object]
if (j === 0 && arguments[j]) {
if (arguments[j].toString() === '[object Object]') {
var s = [];
for (var k = 0, l = arguments[j].length; k < l; k++) {
s.push(arguments[j][k]);
}
arg = s.join('');
}
}
log.args.push({ i: j, o: arg, s: arg ? arg.toString(): 'null'});
}
var retval;
try {
retval = this[targetMethod].apply(this, arguments); // might crash (Frida bug?)
log.returns = { val: retval, str: retval ? retval.toString() : null };
} catch (e) {
console.error(e);
}
LOG(log, { c: Color.Blue });
return retval;
}
}
}
// remove duplicates from array
function uniqBy(array, key) {
var seen = {};
return array.filter(function (item) {
var k = key(item);
return seen.hasOwnProperty(k) ? false : (seen[k] = true);
});
}
var Main = function() {
Java.perform(function () { // avoid java.lang.ClassNotFoundException
[
// "java.io.File",
'java.net.Socket',
'com.package.MyCustomClass'
].forEach(traceClass);
});
};
Java.perform(Main);

Related

Dart: Class members seem to be wrong when access from a separate class

Anyone know if this is a Dart bug or is it my misunderstanding of how Dart coding works?
I am learning Dart to investigate feasibility of eventually using Flutter; however, while exploring the language, I found a weird behavior (maybe a bug). I tried repro'ing it by writing a similar pattern of code, but have yet to figure out what causes it. In the attached code, I wrote a quicksort class. In that class, it counts the number of times the "sort" method is recursed and saves the count in a class member called "recurseCount".
From the main() class, if I use the QuickSort class directly, I have no issue getting back the recurseCount member; however, if I call it from a different class (called "Tester"), I do not get the correct value for "recurseCount". Why would calling a class from a separate class cause members to not provide the correct values?
import 'package:test/test.dart';
import 'dart:math' as _math;
// ***********************
enum SortOrder { ascending, descending, unsorted }
class QuickSort {
List list = [];
SortOrder sortOrder = SortOrder.unsorted;
int recurseCount = 0;
QuickSort({this.list}) {
if (list != null && list.length > 1) {
list = sort(useRandomPivot: true);
}
}
List sort(
{List iList,
int leftIndex = 0,
int rightIndex,
bool useRandomPivot = true}) {
if (iList != null) list = iList;
if (list.isEmpty) return [];
rightIndex ??= list.length - 1;
if (rightIndex > list.length - 1) rightIndex = list.length - 1;
if (leftIndex < rightIndex) {
recurseCount++;
var partitionIndex =
_partition(leftIndex, rightIndex, useRandomPivot: useRandomPivot);
if (partitionIndex == -1) {
//already sorted List
if (sortOrder == SortOrder.ascending) {
return list;
} else {
//SortOrder.descending
list = list.reversed.toList(); // Time Complexity of O(n)
sortOrder = SortOrder.ascending;
return list;
}
} else {
sort(leftIndex: leftIndex, rightIndex: partitionIndex - 1);
sort(leftIndex: partitionIndex + 1, rightIndex: rightIndex);
}
} else {
sortOrder = SortOrder.ascending;
}
return list;
}
int _partition(int leftIndex, int rightIndex, {bool useRandomPivot = true}) {
// in case the array is already sorted from the start; only run through the partition'ing one time
// note: regardless of ascending or descending order
if (leftIndex == 0 && rightIndex >= list.length - 1) {
sortOrder = checkSorting(list);
if (sortOrder != SortOrder.unsorted) {
return -1;
}
if (useRandomPivot) {
var random = _math.Random();
var randomIndex = random.nextInt(rightIndex - leftIndex);
_swapElements(randomIndex, rightIndex);
}
}
int pivotVal = list[rightIndex]; //select the last item as the pivot
var headIndex = leftIndex - 1;
for (var scanIndex = leftIndex; scanIndex < rightIndex; scanIndex++) {
if (list[scanIndex] <= pivotVal) {
headIndex++;
_swapElements(headIndex, scanIndex);
}
}
var partitionIndex = headIndex + 1;
_swapElements(partitionIndex, rightIndex);
return partitionIndex;
}
void _swapElements(position1, position2) {
int tempVal = list[position1];
list[position1] = list[position2];
list[position2] = tempVal;
}
SortOrder checkSorting(List arr) {
var isAsc = true;
var isDesc = true;
for (var i = 0; i < arr.length - 1; i++) {
if (arr[i] < arr[i + 1]) isDesc = false;
if (arr[i] > arr[i + 1]) isAsc = false;
if (!isDesc && !isAsc) break; // not sorted Asc or Desc
}
if (isAsc) {
return SortOrder.ascending;
} else if (isDesc) return SortOrder.descending;
return SortOrder.unsorted;
}
}
// ***********************TESTS*********************************
num log2(num n) => _math.log(n) / _math.ln2;
List getRandomIntList({int min = 0, int max = 10000, int len}) {
var random = _math.Random();
var tempList = List(len);
for (var i = 0; i < len; i++) {
tempList[i] = random.nextInt(max - min);
}
return tempList;
}
class Tester {
static num _runControlTest(List list) {
var stopwatch = Stopwatch();
stopwatch.start();
list.sort();
stopwatch.stop();
return stopwatch.elapsedMicroseconds;
}
static void runTests(List list, String groupName,
{bool useRandomPivot = false, bool sortFromConstructor = false}) {
// CONTROL
var controlElapsedTimeMicroSec = 0;
controlElapsedTimeMicroSec = _runControlTest(list);
// END CONTROL
var expectedRecursionCountLogN = log2(list.length).ceil();
var expectedRecursionCountNLogN = list.length * expectedRecursionCountLogN;
var qs = QuickSort();
var stopwatch = Stopwatch();
stopwatch.start();
list =
qs.sort(iList: list, useRandomPivot: useRandomPivot); // METHOD TO TEST
stopwatch.stop();
var elapsedTimeMicroSec = stopwatch.elapsedMicroseconds;
var recursionCount = qs
.recurseCount; //NOTE (BUG in Dart?): unable to get the recurseCount correctly from within this class/method
group(groupName, () {
var testSubject =
'Time Taken: ${controlElapsedTimeMicroSec} microseconds';
var reason =
'The built in sort took ${controlElapsedTimeMicroSec} microseconds, while the test took ${elapsedTimeMicroSec}.';
test(testSubject, () {
expect(
elapsedTimeMicroSec, lessThanOrEqualTo(controlElapsedTimeMicroSec),
reason: reason);
});
testSubject =
'Time Complexity: ${recursionCount} vs ${expectedRecursionCountNLogN}';
reason =
'Time Complexity of ${recursionCount} is greater than either range (LogN) ${expectedRecursionCountLogN} or (N*LogN) ${expectedRecursionCountNLogN}';
test(testSubject, () {
expect(recursionCount, lessThanOrEqualTo(expectedRecursionCountNLogN),
reason: reason);
});
});
}
}
void main() {
var min = 0;
var len = 1000000;
var max = len;
var originalList = getRandomIntList(min: min, max: max, len: len);
var list = List.from(originalList);
// BUG? When called within this Tester.runTests the sort method does NOT return the correct recurseCount
Tester.runTests(list, 'UNSORTED_RIGHT_PIVOT', useRandomPivot: false);
list = List.from(originalList);
var qs = QuickSort();
// When called directly from main() the sort method DOES return the correct recurseCount
var stopwatch = Stopwatch()..start();
qs.sort(iList: list, useRandomPivot: true); //METHOD TO TEST
stopwatch.stop();
group('UNSORTED_RANDOM_PIVOT', () {
test('Time Taken: ${stopwatch.elapsedMicroseconds} microseconds', () {
expect(stopwatch.elapsedMicroseconds,
lessThanOrEqualTo(Tester._runControlTest(originalList)));
});
var nLogN = (list.length * (log2(list.length).ceil()));
test('Time Complexity: ${qs.recurseCount} vs $nLogN', () {
expect(qs.recurseCount, lessThanOrEqualTo(nLogN));
});
});
}

Cant stream video (PFFile) from parse server

I am having trouble streaming video with my iOS app from URL of a PFFile uploaded in my database. I used Heroku and AWS and I still have the same issue. It used to work fine when the files were hosted in the old parse server.
the PFFile url works fine when I open it in a chrome web browser but not in safari nor in the iOS app.
the following is the link of the video:
http://shuuapp.herokuapp.com/parse/files/wnQeou0L4klDelSEtMOX6SxXRVKu1f3sKl6vg349/24092609eadcc049f711aafbd59c1a18_movie.mp4
Its exactly the same issue as the issue mentioned in the link below:
iOS - Can't stream video from Parse Backend
parse-server doesn't seem to be supporting streaming in Safari/iOS and the solution is the enable it using express & GridStore as follows,
parse-server-example\node_modules\parse-server\lib\Routers\FilesRouter
{
key: 'getHandler',
value: function getHandler(req, res, content) {
var config = new _Config2.default(req.params.appId);
var filesController = config.filesController;
var filename = req.params.filename;
var video = '.mp4'
var lastFourCharacters = video.substr(video.length - 4);
if (lastFourCharacters == '.mp4') {
filesController.handleVideoStream(req, res, filename).then(function (data) {
}).catch(function (err) {
console.log('404FilesRouter');
res.status(404);
res.set('Content-Type', 'text/plain');
res.end('File not found.');
});
}else{
filesController.getFileData(config, filename).then(function (data) {
res.status(200);
res.end(data);
}).catch(function (err) {
res.status(404);
res.set('Content-Type', 'text/plain');
res.end('File not found.');
});
}
}
} , ...
parse-server-example\node_modules\parse-server\lib\Controllers\FilesController
_createClass(FilesController, [{
key: 'getFileData',
value: function getFileData(config, filename) {
return this.adapter.getFileData(filename);
}
},{
key: 'handleVideoStream',
value: function handleVideoStream(req, res, filename) {
return this.adapter.handleVideoStream(req, res, filename);
}
}, ...
parse-server-example\node_modules\parse-server\lib\Adapters\Files\GridStoreAdapter
... , {
key: 'handleVideoStream',
value: function handleVideoStream(req, res, filename) {
return this._connect().then(function (database) {
return _mongodb.GridStore.exist(database, filename).then(function () {
var gridStore = new _mongodb.GridStore(database, filename, 'r');
gridStore.open(function(err, GridFile) {
if(!GridFile) {
res.send(404,'Not Found');
return;
}
console.log('filename');
StreamGridFile(GridFile, req, res);
});
});
})
}
}, ...
Bottom of GridStore Adapter
function StreamGridFile(GridFile, req, res) {
var buffer_size = 1024 * 1024;//1024Kb
if (req.get('Range') != null) { //was: if(req.headers['range'])
// Range request, partialle stream the file
console.log('Range Request');
var parts = req.get('Range').replace(/bytes=/, "").split("-");
var partialstart = parts[0];
var partialend = parts[1];
var start = partialstart ? parseInt(partialstart, 10) : 0;
var end = partialend ? parseInt(partialend, 10) : GridFile.length - 1;
var chunksize = (end - start) + 1;
if(chunksize == 1){
start = 0;
partialend = false;
}
if(!partialend){
if(((GridFile.length-1) - start) < (buffer_size) ){
end = GridFile.length - 1;
}else{
end = start + (buffer_size);
}
chunksize = (end - start) + 1;
}
if(start == 0 && end == 2){
chunksize = 1;
}
res.writeHead(206, {
'Cache-Control': 'no-cache',
'Content-Range': 'bytes ' + start + '-' + end + '/' + GridFile.length,
'Accept-Ranges': 'bytes',
'Content-Length': chunksize,
'Content-Type': 'video/mp4',
});
GridFile.seek(start, function () {
// get GridFile stream
var stream = GridFile.stream(true);
var ended = false;
var bufferIdx = 0;
var bufferAvail = 0;
var range = (end - start) + 1;
var totalbyteswanted = (end - start) + 1;
var totalbyteswritten = 0;
// write to response
stream.on('data', function (buff) {
bufferAvail += buff.length;
//Ok check if we have enough to cover our range
if(bufferAvail < range) {
//Not enough bytes to satisfy our full range
if(bufferAvail > 0)
{
//Write full buffer
res.write(buff);
totalbyteswritten += buff.length;
range -= buff.length;
bufferIdx += buff.length;
bufferAvail -= buff.length;
}
}
else{
//Enough bytes to satisfy our full range!
if(bufferAvail > 0) {
var buffer = buff.slice(0,range);
res.write(buffer);
totalbyteswritten += buffer.length;
bufferIdx += range;
bufferAvail -= range;
}
}
if(totalbyteswritten >= totalbyteswanted) {
// totalbytes = 0;
GridFile.close();
res.end();
this.destroy();
}
});
});
}else{
// res.end(GridFile);
// stream back whole file
res.header('Cache-Control', 'no-cache');
res.header('Connection', 'keep-alive');
res.header("Accept-Ranges", "bytes");
res.header('Content-Type', 'video/mp4');
res.header('Content-Length', GridFile.length);
var stream = GridFile.stream(true).pipe(res);
}
};
P.S
The original answer is given by #Bragegs here - https://github.com/ParsePlatform/parse-server/issues/1440#issuecomment-212815625 .

Detecting TabMove in firefox add-on

Tried out the impl. given in : https://developer.mozilla.org/en-US/Add-ons/Code_snippets/Tabbed_browser#Notification when a tab is added or removed
for tracking 'tabmove'. Didn't work.
Would appreciate any help in this regard.
BTW, already tried below code. Only 'TabOpen' event is received. 'TabClose' and 'TabMove' does not work:
var browserWindows = require("sdk/windows").browserWindows;
var activeWindow = browserWindows ? browserWindows.activeWindow : {};
var browserWindow = activeWindow ? require("sdk/view/core").viewFor(activeWindow) : {};
var DOMWindow = browserWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
var exampleTabAdded = function(event) {
var browser = DOMWindow.gBrowser.getBrowserForTab(event.target);
console.log('tab added: '+ event.target);
};
var exampleTabMoved = function(event) {
var browser = DOMWindow.gBrowser.getBrowserForTab(event.target);
console.log('tab moved: '+ event.target);
};
function exampleTabRemoved(event) {
var browser = gBrowser.getBrowserForTab(event.target);
console.log('tab removed: '+ event.target);
}
function exampleTabSelected(event) {
var browser = gBrowser.getBrowserForTab(event.target);
console.log('tab selected: '+ event.target);
}
var container = DOMWindow.gBrowser.tabContainer;
container.addEventListener("TabMove", exampleTabMoved, false);
container.addEventListener("TabOpen", exampleTabAdded, false);
container.addEventListener("TabClose", exampleTabRemoved, false);
container.addEventListener("TabSelect", exampleTabSelected, false);
Thanks
This seems to work. Uses both sdk api's as well as XUL content document.
If there is a better way to handle 'tabmove', please do post the answer.
var tabs = require("sdk/tabs");
var { modelFor } = require("sdk/model/core");
var { viewFor } = require("sdk/view/core");
var tab_utils = require("sdk/tabs/utils");
var contentDocumentMap = new Map();
function mapHighLevelTabToLowLevelContentDocument(tab) {
var lowLevelTab = viewFor(tab);
var browser = tab_utils.getBrowserForTab(lowLevelTab);
return browser.contentDocument;
}
function onOpen(tab) {
tab.on("pageshow", logShow);
tab.on("activate", logActivate);
tab.on("deactivate", logDeactivate);
tab.on("close", logClose);
}
function logShow(tab) {
var contentWindow = mapHighLevelTabToLowLevelContentDocument(tab);
if ((contentWindow.URL === 'about:newtab') || (contentWindow.URL === 'about:blank')) {
return;
}
if (contentDocumentMap.has(contentWindow)) {
return;
}
contentDocumentMap.set(contentWindow, tab.id.toString());
}
function logActivate(tab) {
var contentWindow = mapHighLevelTabToLowLevelContentDocument(tab);
if ((contentWindow.URL === 'about:newtab') || (contentWindow.URL === 'about:blank')) {
return;
}
if (contentDocumentMap.has(contentWindow)) {
return;
}
contentDocumentMap.set(contentWindow, tab.id.toString());
}
function logDeactivate(tab) {
setTimeout(function() {
var windows = require("sdk/windows").browserWindows;
for (let window of windows) {
var activeTabContentWindow = mapHighLevelTabToLowLevelContentDocument(window.tabs.activeTab);
var activeTabId = window.tabs.activeTab.id.toString();
if ((contentDocumentMap.has(activeTabContentWindow)) && (contentDocumentMap.get(activeTabContentWindow) !== activeTabId)) {
console.log('M O V E D. url: '+ window.tabs.activeTab.url);
console.log('from tabid: '+ contentDocumentMap.get(activeTabContentWindow) + ' to tabid: ' + activeTabId);
contentDocumentMap.delete(activeTabContentWindow);
contentDocumentMap.set(activeTabContentWindow, activeTabId);
}
}
}, 150);
}
function logClose(tab) {
var targetTabId = tab.id.toString();
setTimeout(function() {
var windows = require("sdk/windows").browserWindows;
for (let window of windows) {
var activeTabContentWindow = mapHighLevelTabToLowLevelContentDocument(window.tabs.activeTab);
var activeTabId = window.tabs.activeTab.id.toString();
if (contentDocumentMap.has(activeTabContentWindow)) {
if (contentDocumentMap.get(activeTabContentWindow) !== activeTabId) {
console.log('M O V E D. url: '+ window.tabs.activeTab.url);
console.log('from tabid: '+ contentDocumentMap.get(activeTabContentWindow) + ' to tabid: ' + activeTabId);
contentDocumentMap.delete(activeTabContentWindow);
contentDocumentMap.set(activeTabContentWindow, activeTabId);
}
else if (targetTabId === activeTabId){
contentDocumentMap.delete(activeTabContentWindow);
}
}
}
}, 150);
}
tabs.on('open', onOpen);

Using dart to create a javascript library

The problem
I'm currently working on a JavaScript library, and in order to reduce the amount of bugs I thought that my library might benefit from using Dart's static typing mechanism. First, because my lib wasn't doing any interop neither with HTML nor with other JavaScript libraries, only pure javascript object manipulation stuff. However I didn't find any info on the net showing how it is possible to build a JS library using dart. So I've tried to do that myself, created initial dart file:
library Repo;
class Type {
final String name;
final TypeCategory category;
Type(String name, TypeCategory category) : name = name, category = category {
category.types[name] = this;
}
}
class TypeCategory {
final String name;
final Map<String, Type> types = new Map();
TypeCategory(this.name);
}
class Branch {
}
class Descriptor {
}
class TableDescriptor extends Descriptor {
TableDescriptor.ctor() {
}
}
class Repo {
Descriptor descriptor(String name) {
}
Branch branch(String name) {
}
void Merge() {
}
}
main() {
return Repo;
}
Compiled it to JavaScript using dart2js to see how I'm doing:
// Generated by dart2js, the Dart to JavaScript compiler version: 1.3.6.
// The code supports the following hooks:
// dartPrint(message):
// if this function is defined it is called instead of the Dart [print]
// method.
//
// dartMainRunner(main, args):
// if this function is defined, the Dart [main] method will not be invoked
// directly. Instead, a closure that will invoke [main], and its arguments
// [args] is passed to [dartMainRunner].
(function($) {
function dart(){ this.x = 0 }var A = new dart;
delete A.x;
var B = new dart;
delete B.x;
var C = new dart;
delete C.x;
var D = new dart;
delete D.x;
var E = new dart;
delete E.x;
var F = new dart;
delete F.x;
var G = new dart;
delete G.x;
var H = new dart;
delete H.x;
var J = new dart;
delete J.x;
var K = new dart;
delete K.x;
var L = new dart;
delete L.x;
var M = new dart;
delete M.x;
var N = new dart;
delete N.x;
var O = new dart;
delete O.x;
var P = new dart;
delete P.x;
var Q = new dart;
delete Q.x;
var R = new dart;
delete R.x;
var S = new dart;
delete S.x;
var T = new dart;
delete T.x;
var U = new dart;
delete U.x;
var V = new dart;
delete V.x;
var W = new dart;
delete W.x;
var X = new dart;
delete X.x;
var Y = new dart;
delete Y.x;
var Z = new dart;
delete Z.x;
function Isolate() {}
init();
$ = Isolate.$isolateProperties;
var $$ = {};
(function (reflectionData) {
"use strict";
function map(x){x={x:x};delete x.x;return x}
function processStatics(descriptor) {
for (var property in descriptor) {
if (!hasOwnProperty.call(descriptor, property)) continue;
if (property === "^") continue;
var element = descriptor[property];
var firstChar = property.substring(0, 1);
var previousProperty;
if (firstChar === "+") {
mangledGlobalNames[previousProperty] = property.substring(1);
var flag = descriptor[property];
if (flag > 0) descriptor[previousProperty].$reflectable = flag;
if (element && element.length) init.typeInformation[previousProperty] = element;
} else if (firstChar === "#") {
property = property.substring(1);
$[property]["#"] = element;
} else if (firstChar === "*") {
globalObject[previousProperty].$defaultValues = element;
var optionalMethods = descriptor.$methodsWithOptionalArguments;
if (!optionalMethods) {
descriptor.$methodsWithOptionalArguments = optionalMethods = {}
}
optionalMethods[property] = previousProperty;
} else if (typeof element === "function") {
globalObject[previousProperty = property] = element;
functions.push(property);
init.globalFunctions[property] = element;
} else if (element.constructor === Array) {
addStubs(globalObject, element, property, true, descriptor, functions);
} else {
previousProperty = property;
var newDesc = {};
var previousProp;
for (var prop in element) {
if (!hasOwnProperty.call(element, prop)) continue;
firstChar = prop.substring(0, 1);
if (prop === "static") {
processStatics(init.statics[property] = element[prop]);
} else if (firstChar === "+") {
mangledNames[previousProp] = prop.substring(1);
var flag = element[prop];
if (flag > 0) element[previousProp].$reflectable = flag;
} else if (firstChar === "#" && prop !== "#") {
newDesc[prop.substring(1)]["#"] = element[prop];
} else if (firstChar === "*") {
newDesc[previousProp].$defaultValues = element[prop];
var optionalMethods = newDesc.$methodsWithOptionalArguments;
if (!optionalMethods) {
newDesc.$methodsWithOptionalArguments = optionalMethods={}
}
optionalMethods[prop] = previousProp;
} else {
var elem = element[prop];
if (prop !== "^" && elem != null && elem.constructor === Array && prop !== "<>") {
addStubs(newDesc, elem, prop, false, element, []);
} else {
newDesc[previousProp = prop] = elem;
}
}
}
$$[property] = [globalObject, newDesc];
classes.push(property);
}
}
}
function addStubs(descriptor, array, name, isStatic, originalDescriptor, functions) {
var f, funcs = [originalDescriptor[name] = descriptor[name] = f = array[0]];
f.$stubName = name;
functions.push(name);
for (var index = 0; index < array.length; index += 2) {
f = array[index + 1];
if (typeof f != "function") break;
f.$stubName = array[index + 2];
funcs.push(f);
if (f.$stubName) {
originalDescriptor[f.$stubName] = descriptor[f.$stubName] = f;
functions.push(f.$stubName);
}
}
for (var i = 0; i < funcs.length; index++, i++) {
funcs[i].$callName = array[index + 1];
}
var getterStubName = array[++index];
array = array.slice(++index);
var requiredParameterInfo = array[0];
var requiredParameterCount = requiredParameterInfo >> 1;
var isAccessor = (requiredParameterInfo & 1) === 1;
var isSetter = requiredParameterInfo === 3;
var isGetter = requiredParameterInfo === 1;
var optionalParameterInfo = array[1];
var optionalParameterCount = optionalParameterInfo >> 1;
var optionalParametersAreNamed = (optionalParameterInfo & 1) === 1;
var isIntercepted = requiredParameterCount + optionalParameterCount != funcs[0].length;
var functionTypeIndex = array[2];
var unmangledNameIndex = 2 * optionalParameterCount + requiredParameterCount + 3;
var isReflectable = array.length > unmangledNameIndex;
if (getterStubName) {
f = tearOff(funcs, array, isStatic, name, isIntercepted);
f.getterStub = true;
if (isStatic) init.globalFunctions[name] = f;
originalDescriptor[getterStubName] = descriptor[getterStubName] = f;
funcs.push(f);
if (getterStubName) functions.push(getterStubName);
f.$stubName = getterStubName;
f.$callName = null;
if (isIntercepted) init.interceptedNames[getterStubName] = true;
}
if (isReflectable) {
for (var i = 0; i < funcs.length; i++) {
funcs[i].$reflectable = 1;
funcs[i].$reflectionInfo = array;
}
var mangledNames = isStatic ? init.mangledGlobalNames : init.mangledNames;
var unmangledName = array[unmangledNameIndex];
var reflectionName = unmangledName;
if (getterStubName) mangledNames[getterStubName] = reflectionName;
if (isSetter) {
reflectionName += "=";
} else if (!isGetter) {
reflectionName += ":" + requiredParameterCount + ":" + optionalParameterCount;
}
mangledNames[name] = reflectionName;
funcs[0].$reflectionName = reflectionName;
funcs[0].$metadataIndex = unmangledNameIndex + 1;
if (optionalParameterCount) descriptor[unmangledName + "*"] = funcs[0];
}
}
function tearOffGetterNoCsp(funcs, reflectionInfo, name, isIntercepted) {
return isIntercepted
? new Function("funcs", "reflectionInfo", "name", "H", "c",
"return function tearOff_" + name + (functionCounter++)+ "(x) {" +
"if (c === null) c = H.closureFromTearOff(" +
"this, funcs, reflectionInfo, false, [x], name);" +
"return new c(this, funcs[0], x, name);" +
"}")(funcs, reflectionInfo, name, H, null)
: new Function("funcs", "reflectionInfo", "name", "H", "c",
"return function tearOff_" + name + (functionCounter++)+ "() {" +
"if (c === null) c = H.closureFromTearOff(" +
"this, funcs, reflectionInfo, false, [], name);" +
"return new c(this, funcs[0], null, name);" +
"}")(funcs, reflectionInfo, name, H, null)
}
function tearOffGetterCsp(funcs, reflectionInfo, name, isIntercepted) {
var cache = null;
return isIntercepted
? function(x) {
if (cache === null) cache = H.closureFromTearOff(this, funcs, reflectionInfo, false, [x], name);
return new cache(this, funcs[0], x, name)
}
: function() {
if (cache === null) cache = H.closureFromTearOff(this, funcs, reflectionInfo, false, [], name);
return new cache(this, funcs[0], null, name)
}
}
function tearOff(funcs, reflectionInfo, isStatic, name, isIntercepted) {
var cache;
return isStatic
? function() {
if (cache === void 0) cache = H.closureFromTearOff(this, funcs, reflectionInfo, true, [], name).prototype;
return cache;
}
: tearOffGetter(funcs, reflectionInfo, name, isIntercepted);
}
var functionCounter = 0;
var tearOffGetter = (typeof dart_precompiled == "function")
? tearOffGetterCsp : tearOffGetterNoCsp;
if (!init.libraries) init.libraries = [];
if (!init.mangledNames) init.mangledNames = map();
if (!init.mangledGlobalNames) init.mangledGlobalNames = map();
if (!init.statics) init.statics = map();
if (!init.typeInformation) init.typeInformation = map();
if (!init.globalFunctions) init.globalFunctions = map();
if (!init.interceptedNames) init.interceptedNames = map();
var libraries = init.libraries;
var mangledNames = init.mangledNames;
var mangledGlobalNames = init.mangledGlobalNames;
var hasOwnProperty = Object.prototype.hasOwnProperty;
var length = reflectionData.length;
for (var i = 0; i < length; i++) {
var data = reflectionData[i];
var name = data[0];
var uri = data[1];
var metadata = data[2];
var globalObject = data[3];
var descriptor = data[4];
var isRoot = !!data[5];
var fields = descriptor && descriptor["^"];
var classes = [];
var functions = [];
processStatics(descriptor);
libraries.push([name, uri, classes, functions, metadata, fields, isRoot,
globalObject]);
}
})
([
["Repo", "repo.dart", , F, {
"^": "",
main: function() {
return C.Type_Jeh;
}
},
1],
["_js_helper", "dart:_js_helper", , H, {
"^": "",
createRuntimeType: function($name) {
return new H.TypeImpl($name, null);
},
TypeImpl: {
"^": "Object;_typeName,_unmangledName"
}
}],
["dart.core", "dart:core", , P, {
"^": "",
Null: {
"^": "Object;"
},
Object: {
"^": ";"
}
}],
]);
Isolate.$finishClasses($$, $, null);
$$ = null;
// Runtime type support
// getInterceptor methods
C.Type_Jeh = H.createRuntimeType('Repo');
$.libraries_to_load = {};
$.Closure_functionCounter = 0;
$.BoundClosure_selfFieldNameCache = null;
$.BoundClosure_receiverFieldNameCache = null;
init.functionAliases = {};
;
init.metadata = [];
$ = null;
Isolate = Isolate.$finishIsolateConstructor(Isolate);
$ = new Isolate();
function convertToFastObject(properties) {
function MyClass() {};
MyClass.prototype = properties;
new MyClass();
return properties;
}
A = convertToFastObject(A);
B = convertToFastObject(B);
C = convertToFastObject(C);
D = convertToFastObject(D);
E = convertToFastObject(E);
F = convertToFastObject(F);
G = convertToFastObject(G);
H = convertToFastObject(H);
J = convertToFastObject(J);
K = convertToFastObject(K);
L = convertToFastObject(L);
M = convertToFastObject(M);
N = convertToFastObject(N);
O = convertToFastObject(O);
P = convertToFastObject(P);
Q = convertToFastObject(Q);
R = convertToFastObject(R);
S = convertToFastObject(S);
T = convertToFastObject(T);
U = convertToFastObject(U);
V = convertToFastObject(V);
W = convertToFastObject(W);
X = convertToFastObject(X);
Y = convertToFastObject(Y);
Z = convertToFastObject(Z);
// BEGIN invoke [main].
;(function (callback) {
if (typeof document === "undefined") {
callback(null);
return;
}
if (document.currentScript) {
callback(document.currentScript);
return;
}
var scripts = document.scripts;
function onLoad(event) {
for (var i = 0; i < scripts.length; ++i) {
scripts[i].removeEventListener("load", onLoad, false);
}
callback(event.target);
}
for (var i = 0; i < scripts.length; ++i) {
scripts[i].addEventListener("load", onLoad, false);
}
})(function(currentScript) {
init.currentScript = currentScript;
if (typeof dartMainRunner === "function") {
dartMainRunner(F.main, []);
} else {
F.main([]);
}
});
// END invoke [main].
function init() {
Isolate.$isolateProperties = {};
function generateAccessor(fieldDescriptor, accessors, cls) {
var fieldInformation = fieldDescriptor.split("-");
var field = fieldInformation[0];
var len = field.length;
var code = field.charCodeAt(len - 1);
var reflectable;
if (fieldInformation.length > 1)
reflectable = true;
else
reflectable = false;
code = code >= 60 && code <= 64 ? code - 59 : code >= 123 && code <= 126 ? code - 117 : code >= 37 && code <= 43 ? code - 27 : 0;
if (code) {
var getterCode = code & 3;
var setterCode = code >> 2;
var accessorName = field = field.substring(0, len - 1);
var divider = field.indexOf(":");
if (divider > 0) {
accessorName = field.substring(0, divider);
field = field.substring(divider + 1);
}
if (getterCode) {
var args = getterCode & 2 ? "receiver" : "";
var receiver = getterCode & 1 ? "this" : "receiver";
var body = "return " + receiver + "." + field;
var property = cls + ".prototype.get$" + accessorName + "=";
var fn = "function(" + args + "){" + body + "}";
if (reflectable)
accessors.push(property + "$reflectable(" + fn + ");\n");
else
accessors.push(property + fn + ";\n");
}
if (setterCode) {
var args = setterCode & 2 ? "receiver, value" : "value";
var receiver = setterCode & 1 ? "this" : "receiver";
var body = receiver + "." + field + " = value";
var property = cls + ".prototype.set$" + accessorName + "=";
var fn = "function(" + args + "){" + body + "}";
if (reflectable)
accessors.push(property + "$reflectable(" + fn + ");\n");
else
accessors.push(property + fn + ";\n");
}
}
return field;
}
Isolate.$isolateProperties.$generateAccessor = generateAccessor;
function defineClass(name, cls, fields) {
var accessors = [];
var str = "function " + cls + "(";
var body = "";
for (var i = 0; i < fields.length; i++) {
if (i != 0)
str += ", ";
var field = generateAccessor(fields[i], accessors, cls);
var parameter = "parameter_" + field;
str += parameter;
body += "this." + field + " = " + parameter + ";\n";
}
str += ") {\n" + body + "}\n";
str += cls + ".builtin$cls=\"" + name + "\";\n";
str += "$desc=$collectedClasses." + cls + ";\n";
str += "if($desc instanceof Array) $desc = $desc[1];\n";
str += cls + ".prototype = $desc;\n";
if (typeof defineClass.name != "string") {
str += cls + ".name=\"" + cls + "\";\n";
}
str += accessors.join("");
return str;
}
var inheritFrom = function() {
function tmp() {
}
var hasOwnProperty = Object.prototype.hasOwnProperty;
return function(constructor, superConstructor) {
tmp.prototype = superConstructor.prototype;
var object = new tmp();
var properties = constructor.prototype;
for (var member in properties)
if (hasOwnProperty.call(properties, member))
object[member] = properties[member];
object.constructor = constructor;
constructor.prototype = object;
return object;
};
}();
Isolate.$finishClasses = function(collectedClasses, isolateProperties, existingIsolateProperties) {
var pendingClasses = {};
if (!init.allClasses)
init.allClasses = {};
var allClasses = init.allClasses;
var hasOwnProperty = Object.prototype.hasOwnProperty;
if (typeof dart_precompiled == "function") {
var constructors = dart_precompiled(collectedClasses);
} else {
var combinedConstructorFunction = "function $reflectable(fn){fn.$reflectable=1;return fn};\n" + "var $desc;\n";
var constructorsList = [];
}
for (var cls in collectedClasses) {
if (hasOwnProperty.call(collectedClasses, cls)) {
var desc = collectedClasses[cls];
if (desc instanceof Array)
desc = desc[1];
var classData = desc["^"], supr, name = cls, fields = classData;
if (typeof classData == "string") {
var split = classData.split("/");
if (split.length == 2) {
name = split[0];
fields = split[1];
}
}
var s = fields.split(";");
fields = s[1] == "" ? [] : s[1].split(",");
supr = s[0];
split = supr.split(":");
if (split.length == 2) {
supr = split[0];
var functionSignature = split[1];
if (functionSignature)
desc.$signature = function(s) {
return function() {
return init.metadata[s];
};
}(functionSignature);
}
if (typeof dart_precompiled != "function") {
combinedConstructorFunction += defineClass(name, cls, fields);
constructorsList.push(cls);
}
if (supr)
pendingClasses[cls] = supr;
}
}
if (typeof dart_precompiled != "function") {
combinedConstructorFunction += "return [\n " + constructorsList.join(",\n ") + "\n]";
var constructors = new Function("$collectedClasses", combinedConstructorFunction)(collectedClasses);
combinedConstructorFunction = null;
}
for (var i = 0; i < constructors.length; i++) {
var constructor = constructors[i];
var cls = constructor.name;
var desc = collectedClasses[cls];
var globalObject = isolateProperties;
if (desc instanceof Array) {
globalObject = desc[0] || isolateProperties;
desc = desc[1];
}
allClasses[cls] = constructor;
globalObject[cls] = constructor;
}
constructors = null;
var finishedClasses = {};
init.interceptorsByTag = Object.create(null);
init.leafTags = {};
function finishClass(cls) {
var hasOwnProperty = Object.prototype.hasOwnProperty;
if (hasOwnProperty.call(finishedClasses, cls))
return;
finishedClasses[cls] = true;
var superclass = pendingClasses[cls];
if (!superclass || typeof superclass != "string")
return;
finishClass(superclass);
var constructor = allClasses[cls];
var superConstructor = allClasses[superclass];
if (!superConstructor)
superConstructor = existingIsolateProperties[superclass];
var prototype = inheritFrom(constructor, superConstructor);
}
for (var cls in pendingClasses)
finishClass(cls);
};
Isolate.$lazy = function(prototype, staticName, fieldName, getterName, lazyValue) {
var sentinelUndefined = {};
var sentinelInProgress = {};
prototype[fieldName] = sentinelUndefined;
prototype[getterName] = function() {
var result = $[fieldName];
try {
if (result === sentinelUndefined) {
$[fieldName] = sentinelInProgress;
try {
result = $[fieldName] = lazyValue();
} finally {
if (result === sentinelUndefined) {
if ($[fieldName] === sentinelInProgress) {
$[fieldName] = null;
}
}
}
} else {
if (result === sentinelInProgress)
H.throwCyclicInit(staticName);
}
return result;
} finally {
$[getterName] = function() {
return this[fieldName];
};
}
};
};
Isolate.$finishIsolateConstructor = function(oldIsolate) {
var isolateProperties = oldIsolate.$isolateProperties;
function Isolate() {
var hasOwnProperty = Object.prototype.hasOwnProperty;
for (var staticName in isolateProperties)
if (hasOwnProperty.call(isolateProperties, staticName))
this[staticName] = isolateProperties[staticName];
function ForceEfficientMap() {
}
ForceEfficientMap.prototype = this;
new ForceEfficientMap();
}
Isolate.prototype = oldIsolate.prototype;
Isolate.prototype.constructor = Isolate;
Isolate.$isolateProperties = isolateProperties;
Isolate.$finishClasses = oldIsolate.$finishClasses;
return Isolate;
};
}
})()
//# sourceMappingURL=out.js.map
//# sourceMappingURL=out.js.map
And that's it, I've thrown away Dart because I didn't knew what to do with generated JS file, also I was frightened of potentially high amount of time required for keeping the resulting library interface clean and similar to one I'm using with JavaScript.
The question(s)
How do I expose class definitions created in Dart and later use them in JavaScript?
Do you think it's worth it going into Dart when nearly all potential library users will be using JS version instead? (Using dart is already not good for me due to difference in community sizes, this means that less people will find it easy to contribute to my library)
In your opinion, what should I do?
Even though Dart supports this use case, if you target JavaScript developers I would stick with JavaScript.
#AlexandreArdhuin shows in his answer to Expose Dart functions to javascript how you can make a Dart function available to JavaScript.
Under the dart-js-interop are many examples how to do function calls and pass data between Dart and JavaScript.
Wrap dart class into custom element, the Dart object auto expose to javascript.
Assume we have 2 Dart Classes, SlickGrid Class contains Column class in Dart
class SlickGrid{
List<Column> columns;
}
class Column{}
class GridWrap extends HtmlElement {
ShadowRoot shadowRoot;
SlickGrid grid; // here is your cool object
}
compile to javascript, and register custom element, then open javascript console,
//this is SlickGrid object
var grid= document.querySelector('cj-grid').grid;
// this is dart Column Object
var column = grid.columns.$index(0,0);
// call toString function in dart object that produce json string...
column.toString$0()

action script 2.0

Hi I have a small flash as below
public function startApp () : Void
{
mcWindowRoot.refToClass = this;
mcNext = mcWindowRoot;
_oLogoutDelegate = Delegate.create (this, onLogoutHandler);
_oWindowManagerRef.addEventListener ("onLogout", _oLogoutDelegate);
loadWhatNext ();
}
/**
* Enter description here
*
*/
function loadWhatNext (mc : MovieClip) : Void
{
var doneFinish = mcNext.container.attachMovie ("done", "done", mcNext.container.getNextHighestDepth ());
//var returnPage = mcNext.container.attachMovie ("item", "item", mcNext.container.getNextHighestDepth () ,
//{
//_x : 135, _y : 230
//});
var miRefTemp = _oWindowManagerRef;
//returnPage.item_txt.htmlText = _level0.account_Return;
//returnPage.onPress =
doneFinish.onPress = function ()
{
trace ("AccountNext returnPage.onPress doneFinish.onPress" )
trace ("AccountNext miRefTemp " + miRefTemp)
trace ("AccountNext this.refToClass " + this._parent._parent.refToClass)
trace ("AccountNext this " + this)
this._parent._parent.refToClass.closeWindow ();
_oShell.loadWindow( "", null);
}
if (aNextdata != undefined && aNextdata.length > 0)
{
for (var i = 0 ; i < 3; i ++)
{
if (aNextdata [i].text != undefined)
{
var tempItem = mcNext.copy.attachMovie ("item", "item" + i, i,
{
_x : 143, _y : 150 + (i * 20)
});
tempItem.item_txt.htmlText = aNextdata [i].text;
tempItem.url = aNextdata [i].link;
tempItem.refToClass = _refWindow;
var asInterpreter = new asFunctionInterpreter (_oWindowManagerRef._oWindowManagerRef.oController.propertiesMap.get ("BaseURL") , this);
var deepLinks : Object = new Object ();
deepLinks = asInterpreter.getAsSingleURL ( aNextdata [i].link );
tempItem.deepLinks = deepLinks;
trace("Next :: LINKS : " + tempItem.wModule );
tempItem.oShell = _oShell;
tempItem.onPress = function ()
{
if (this.deepLinks.type == "internal")
{
this.oShell.loadWindow( this.deepLinks.wModule , this.deepLinks.wParams);
}
else
{
getURL (this.deepLinks.link, "_blank");
}
this.refToClass.closeWindow ();
}
}
}
} else
{
trace ("end tab " + _refWindow);
}
}
/**
* Enter description here
*
* #param evt
*/
private function onLogoutHandler (evt : Object) : Void
{
_oWindowManagerRef.removeEventListener ("onLogout", _oLogoutDelegate);
closeWindow ();
}
/**
* Enter description here
*
*/
public function closeMyWindow () : Void
{
_global._doNav ('windowType:wclose')
}
/**
* Enter description here
*
*/
public function removeMyWindow () : Void
{
_oWindowManagerRef.removeWindow (idWindow);
}
}
If you can see from this part of the code
if (aNextdata != undefined && aNextdata.length > 0)
I am getting three links one below the other but my problem is only the first link is opening in a new page which is supposed to open in the same page so what should I do for this Please help me thankyou.
Hard to say from your question, but it could be the getUrl-call that is causing your link to open in a new window. The second, optional, parameter to getUrl specifies the window in which the link should open. If you replace
getURL (this.deepLinks.link, "_blank");
with
getURL (this.deepLinks.link);
Your link should open in the same window.

Resources