Related
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));
});
});
}
I found a couple of functions that met my needs, but they don't want to play nice together. The goal is to pull data once a day, then add it to a new column. The history function is fine, and I've got a trigger setup to run it once a day, but it's erroring when attempting to run automatically, and sending me an email with the following.
6/18/18 5:29 PM loadRegionAggregates TypeError: Cannot find function
forEach in object [object Object]. (line 19, file
"Code") time-based 6/18/18 5:29 PM
here's the full code.gs (I bolded the section with line 19, first line of the function)
// Requires a list of typeids, so something like Types!A:A
// https://docs.google.com/spreadsheets/d/1IixV0eNqg19FE6cLzb83G1Ucb0Otl-Jnvm6csAlPKwo/edit?usp=sharing for an example
function loadRegionAggregates(priceIDs,regionID){
if (typeof regionID == 'undefined'){
regionID=10000002;
}
if (typeof priceIDs == 'undefined'){
throw 'Need a list of typeids';
}
var prices = new Array();
var dirtyTypeIds = new Array();
var cleanTypeIds = new Array();
var url="https://market.fuzzwork.co.uk/aggregates/?station=60003760&types=34,35,36,37,38,39,40"
**priceIDs.forEach(function (row) {
row.forEach(function (cell) {
if (typeof(cell) === 'number' ) {
dirtyTypeIds.push(cell);
}**
});
});
cleanTypeIds = dirtyTypeIds.filter(function(v,i,a) {
return a.indexOf(v)===i;
});
prices.push(['TypeID','Buy volume','Buy Weighted Average','Max Buy','Min Buy','Buy Std Dev','Median Buy','Percentile Buy Price','Sell volume','Sell Weighted Average','Max sell','Min Sell','Sell Std Dev','Median Sell','Percentile Sell Price'])
var parameters = {method : "get", payload : ""};
var o,j,temparray,chunk = 100;
for (o=0,j=cleanTypeIds.length; o < j; o+=chunk) {
temparray = cleanTypeIds.slice(o,o+chunk);
Utilities.sleep(100);
var types=temparray.join(",").replace(/,$/,'')
var jsonFeed = UrlFetchApp.fetch(url+types, parameters).getContentText();
var json = JSON.parse(jsonFeed);
if(json) {
for(i in json) {
var price=[parseInt(i),
parseInt(json[i].buy.volume),
parseInt(json[i].buy.weightedAverage),
parseFloat(json[i].buy.max),
parseFloat(json[i].buy.min),
parseFloat(json[i].buy.stddev),
parseFloat(json[i].buy.median),
parseFloat(json[i].buy.percentile),
parseInt(json[i].sell.volume),
parseFloat(json[i].sell.weightedAverage),
parseFloat(json[i].sell.max),
parseFloat(json[i].sell.min),
parseFloat(json[i].sell.stddev),
parseFloat(json[i].sell.median),
parseFloat(json[i].sell.percentile)];
prices.push(price);
}
}
}
return prices;
}
function storeData() {
var sheet = SpreadsheetApp.getActiveSheet();
var datarange = sheet.getDataRange();
var numRows = datarange.getNumRows();
var numColumns = datarange.getNumColumns();
sheet.getRange(1,numColumns + 1).setValue(new Date());
for (var i=2; i <= numRows; i++) {
var prices = sheet.getRange(i, 8).getValue();
sheet.getRange(i, numColumns + 1).setValue(prices);
}
}
I found this link:
TypeError: Cannot find function forEach in object
Which explains some of it, but when the code runs in debug mode, I don't have a range defined, and then the live sheet bugs with:
ReferenceError: "row" is not defined (line 21).
Note: My original code works fine when I run the script locally, just not when the daily timer goes off. I'm assuming the issues listed on the linked query regarding no forEach class on the nested object are applying to whatever runs the triggered .gs
Edit: Ok so i've been working on this all day. I've learned how to set an array var (since I didn't need to change the array, static works) and i've been trying to get the rest of the code adjusted ever since. Here's where I am so far:
// Requires a list of typeids, so something like Types!A:A
// https://docs.google.com/spreadsheets/d/1IixV0eNqg19FE6cLzb83G1Ucb0Otl-Jnvm6csAlPKwo/edit?usp=sharing for an example
function loadRegionAggregates(priceIDs,regionID){
if (typeof regionID == 'undefined'){
regionID=10000002;
}
if (typeof priceIDs == 'undefined'){
priceIDs = [34,35,36,37,38,39,40,11399];
}
var prices = new Array();
var dirtyTypeIds = new Array();
var cleanTypeIds = new Array();
var url="https://market.fuzzwork.co.uk/aggregates/?station=60003760&types=34,35,36,37,38,39,40"
// for (var priceIDs) {
// if (row.hasOwnProperty(column)) {
// var cell = row[column];
// if (typeof cell == "number") {
priceIDs.push(priceIDs);
// }
// }
// }
cleanTypeIds = dirtyTypeIds.filter(function(v,i,a) {
return a.indexOf(v)===i;
});
prices.push(['TypeID','Buy volume','Buy Weighted Average','Max Buy','Min Buy','Buy Std Dev','Median Buy','Percentile Buy Price','Sell volume','Sell Weighted Average','Max sell','Min Sell','Sell Std Dev','Median Sell','Percentile Sell Price'])
var parameters = {method : "get", payload : ""};
var o,j,temparray,chunk = 100;
for (o=0,j=cleanTypeIds.length; o < j; o+=chunk) {
temparray = cleanTypeIds.slice(o,o+chunk);
Utilities.sleep(100);
var types=temparray.join(",").replace(/,$/,'')
var jsonFeed = UrlFetchApp.fetch(url+types, parameters).getContentText();
var json = JSON.parse(jsonFeed);
if(json) {
for(i in json) {
var price=[parseInt(i),
parseInt(json[i].buy.volume),
parseInt(json[i].buy.weightedAverage),
parseFloat(json[i].buy.max),
parseFloat(json[i].buy.min),
parseFloat(json[i].buy.stddev),
parseFloat(json[i].buy.median),
parseFloat(json[i].buy.percentile),
parseInt(json[i].sell.volume),
parseFloat(json[i].sell.weightedAverage),
parseFloat(json[i].sell.max),
parseFloat(json[i].sell.min),
parseFloat(json[i].sell.stddev),
parseFloat(json[i].sell.median),
parseFloat(json[i].sell.percentile)];
prices.push(price);
}
}
}
return prices;
}
function storeData() {
var sheet = SpreadsheetApp.getActiveSheet();
var datarange = sheet.getDataRange();
var numRows = datarange.getNumRows();
var numColumns = datarange.getNumColumns();
sheet.getRange(1,numColumns + 1).setValue(new Date());
for (var i=2; i <= numRows; i++) {
var prices = sheet.getRange(i, 8).getValue();
sheet.getRange(i, numColumns + 1).setValue(prices);
}
}
So far, so good. It's not throwing any more errors on debug, and the column headers are coming in, but it's not bringing in the data anymore from the push.
Help!
I have a code like this
var arr = new Array();
var cnt = 0;
var checkboxes = $('.sel');
var emaillist = document.getElementsByName("elist[]");
var selectedContract = [];
var dispflag = false;
var x = 0;
$.each(checkboxes,function(i,r){
if(r.checked){
arr[cnt++] = r.value;
if(emaillist[x].value != "true"){
dispflag = true;
selectedContract.push(r.value);
}
}
x++;
});
var params = selectedContract.join(':');
if(cnt == 0)
{
alert("No contracts selected.");
}
else
{
url = controllerPath + "/getcontract/contract_id/" + arr + "/custom_action/1";
window.open (url,"Contracts","resizable=1,location=1,status=1,scrollbars=1,width=800,height=600");
}
I want to change arr that give result contract_id to POST method cause when the contract_id more than 500 result, the page shows blank due to URL too large/too long.
I still don't understand how to do it.
Anyone can help me to solve it.
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()
I have re-written the getting-started-with-event-store project to learn what's going on and now for the test CanSaveExistingAggregate() I am getting a WrongExpectedVersionException. The thing is, in order to try and work out what's going on I would like to know what the expected version should be, how can I find this out? In the test, the line repository.Save(firstSaved, Guid.NewGuid(), d => { }); calculates the expected version as 101 and this is where it fails:
[Test]
public void CanSaveExistingAggregate()
{
var savedId = SaveTestAggregateWithoutCustomHeaders(repository, 100 /* excludes TestAggregateCreated */);
var firstSaved = repository.GetById<TestAggregate>(savedId);
Console.WriteLine("version:" + firstSaved.Id);
firstSaved.ProduceEvents(50);
repository.Save(firstSaved, Guid.NewGuid(), d => { });
var secondSaved = repository.GetById<TestAggregate>(savedId);
Assert.AreEqual(150, secondSaved.AppliedEventCount);
}
And the code where the exception is thrown:
public void Save(CommonDomain.IAggregate aggregate, Guid commitId, Action<IDictionary<string, object>> updateHeaders)
{
var commitHeaders = new Dictionary<string, object>
{
{CommitIdHeader, commitId},
{AggregateClrTypeHeader, aggregate.GetType().AssemblyQualifiedName}
};
updateHeaders(commitHeaders);
var streamName = aggregateIdToStreamName(aggregate.GetType(), aggregate.Id);
var newEvents = aggregate.GetUncommittedEvents().Cast<object>().ToList();
var originalVersion = aggregate.Version - newEvents.Count;
var expectedVersion = originalVersion == 0 ? ExpectedVersion.NoStream : originalVersion;
var eventsToSave = newEvents.Select(e => ToEventData(Guid.NewGuid(), e, commitHeaders)).ToList();
if (eventsToSave.Count < WritePageSize)
{
eventStoreConnection.AppendToStream(streamName, expectedVersion, eventsToSave);
}
else
{
var transaction = eventStoreConnection.StartTransaction(streamName, expectedVersion);
var position = 0;
while (position < eventsToSave.Count)
{
var pageEvents = eventsToSave.Skip(position).Take(WritePageSize);
transaction.Write(pageEvents);
position += WritePageSize;
}
transaction.Commit();
}
aggregate.ClearUncommittedEvents();
}
All the other tests pass (except ThrowsOnGetDeletedAggregate() but I'll ask about that later) but I think this is the only test that has expectedVersion != ThrowsOnGetDeletedAggregate()
Well it turns out it was just a mistake when writing the code, rather than
var expectedVersion = originalVersion == 0 ? ExpectedVersion.NoStream : originalVersion;
it should be
var expectedVersion = originalVersion == 0 ? ExpectedVersion.NoStream : originalVersion - 1;