Update web-platform-tests to revision 0f31ab1b094596062154092307bb9ff8e6122533

This commit is contained in:
WPT Sync Bot 2019-01-15 20:35:30 -05:00
parent 96ad6710b1
commit 372e03fe64
32 changed files with 992 additions and 222 deletions

View file

@ -1,6 +1,6 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>Async Clipboard basic tests</title>
<title>Async Clipboard input type validation tests</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
@ -46,6 +46,21 @@ promise_test(async t => {
navigator.clipboard.writeText());
}, "navigator.clipboard.writeText() fails (expect DOMString)");
/* clipboard.writeImageExperimental() */
promise_test(async () => {
const fetched = await fetch(
'http://localhost:8001/clipboard-apis/resources/greenbox.png');
const image = await fetched.blob();
await navigator.clipboard.writeImageExperimental(image);
}, "navigator.clipboard.writeImageExperimental(Blob) succeeds");
promise_test(async t => {
await promise_rejects(t, new TypeError(),
navigator.clipboard.writeImageExperimental());
}, "navigator.clipboard.writeImageExperimental() fails (expect Blob)");
/* clipboard.read() */
@ -62,4 +77,11 @@ promise_test(async () => {
assert_equals(typeof result, "string");
}, "navigator.clipboard.readText() succeeds");
/* clipboard.readImageExperimental() */
promise_test(async () => {
const result = await navigator.clipboard.readImageExperimental();
assert_equals(typeof result, "object");
}, "navigator.clipboard.readImageExperimental() succeeds");
</script>

View file

@ -0,0 +1,57 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>
Async Clipboard writeImageExperimental -> readImageExperimental tests
</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<div>Original Image:</div>
<image id='image-to-copy' src="resources/greenbox.png"></image>
<div>Image after copy/paste:</div>
<image id='image-on-clipboard'></image>
<canvas id="canvas" width="30" height="30"></canvas>
<script>
// Must compare a bitmap as opposed to simply blob data, because an encoded
// image may have different contents depending on encoder.
const getBitmapString = async blob => {
const imageBitmap = await createImageBitmap(blob);
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
ctx.drawImage(imageBitmap, 0,0);
let imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
ctx.clearRect(0, 0, canvas.width, canvas.height);
return imageData.data.toString();
};
const loadBlob = async fileName => {
const fetched = await fetch(fileName);
return await fetched.blob();
}
promise_test(async t => {
const input = await loadBlob(
'http://localhost:8001/clipboard-apis/resources/greenbox.png');
await navigator.clipboard.writeImageExperimental(input);
const output = await navigator.clipboard.readImageExperimental();
document.getElementById('image-on-clipboard').src =
window.URL.createObjectURL(output);
const comparableInput = await getBitmapString(input);
const comparableOutput = await getBitmapString(output);
assert_equals(comparableOutput, comparableInput);
}, "Verify write and read clipboard (DOMString)");
</script>
<br/><br/>
Note: This is a manual test because it writes/reads to the shared system
clipboard and thus cannot be run async with other tests that might interact
with the clipboard.
<br/><br/>
The bottom image should display the same image as the top image.

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 B

View file

@ -0,0 +1,42 @@
<!DOCTYPE html>
<script src='/resources/testharness.js'></script>
<script src='/resources/testharnessreport.js'></script>
<script src='/resources/check-layout-th.js'></script>
<link rel="author" title="David Grogan" href="dgrogan@chromium.org">
<link rel="help" href="https://www.w3.org/TR/css-flexbox-1/#valdef-flex-basis-auto">
<meta name="flags" content="" />
<meta name="assert" content="flex-basis:auto on orthogonal item in horizontal column flexbox is calculated correctly" />
<style>
x-word-h {
display: inline-block;
height: 10px;
width: 20px;
background: blue;
}
x-word-v {
display: inline-block;
height: 20px;
width: 10px;
background: blue;
}
* {
/* This is for easier manual calculations, not necessary to demonstrate behavior. */
line-height: 0;
}
</style>
<div id=flexbox style="width:150px; background:green; height:400px; display:flex; flex-direction:column">
<div style="writing-mode: vertical-rl;background:orange; flex:1 1 auto" data-expected-height=225>
<x-word-v></x-word-v><x-word-v></x-word-v><x-word-v></x-word-v>
</div>
<div style="background:lightblue; flex: 1 1 auto">
<x-word-h></x-word-h><x-word-h></x-word-h><x-word-h></x-word-h>
</div>
</div>
<script>
checkLayout('#flexbox');
</script>

View file

@ -2,48 +2,36 @@
<link rel="help" href="https://drafts.csswg.org/mediaqueries-5/#prefers-color-scheme" />
<script type="text/javascript" src="/resources/testharness.js"></script>
<script type="text/javascript" src="/resources/testharnessreport.js"></script>
<style id="testStyle"> </style>
<script type="text/javascript" src="resources/matchmedia-utils.js"></script>
<script>
var sheet = testStyle.sheet;
query_should_be_css_parseable("(prefers-color-scheme)");
query_should_be_css_parseable("(prefers-color-scheme: no-preference)");
query_should_be_css_parseable("(prefers-color-scheme: light)");
query_should_be_css_parseable("(prefers-color-scheme: dark)");
function query_is_parseable(query) {
try {
sheet.insertRule("@media " + query + "{}", 0);
return sheet.cssRules.length == 1 &&
sheet.cssRules[0].media.mediaText != "not all";
} finally {
while (sheet.cssRules.length)
sheet.deleteRule(0);
}
}
query_should_not_be_css_parseable("(prefers-color-scheme: 0)");
query_should_not_be_css_parseable("(prefers-color-scheme: none)");
query_should_not_be_css_parseable("(prefers-color-scheme: 10px)");
query_should_not_be_css_parseable("(prefers-color-scheme: dark 0)");
query_should_not_be_css_parseable("(prefers-color-scheme: dark light)");
query_should_not_be_css_parseable("(prefers-color-scheme: light/dark)");
function query_should_be_parseable(query) {
test(() => {
assert_true(query_is_parseable(query));
}, "Should be parseable: '" + query + "'");
}
query_should_be_js_parseable("(prefers-color-scheme)");
query_should_be_js_parseable("(prefers-color-scheme: no-preference)");
query_should_be_js_parseable("(prefers-color-scheme: light)");
query_should_be_js_parseable("(prefers-color-scheme: dark)");
function query_should_not_be_parseable(query) {
test(() => {
assert_false(query_is_parseable(query));
}, "Should not be parseable: '" + query + "'");
}
query_should_not_be_js_parseable("(prefers-color-scheme: 0)");
query_should_not_be_js_parseable("(prefers-color-scheme: none)");
query_should_not_be_js_parseable("(prefers-color-scheme: 10px)");
query_should_not_be_js_parseable("(prefers-color-scheme: dark 0)");
query_should_not_be_js_parseable("(prefers-color-scheme: dark light)");
query_should_not_be_js_parseable("(prefers-color-scheme: light/dark)");
query_should_be_parseable("(prefers-color-scheme)");
query_should_be_parseable("(prefers-color-scheme: no-preference)");
query_should_be_parseable("(prefers-color-scheme: light)");
query_should_be_parseable("(prefers-color-scheme: dark)");
query_should_not_be_parseable("(prefers-color-scheme: 0)");
query_should_not_be_parseable("(prefers-color-scheme: none)");
query_should_not_be_parseable("(prefers-color-scheme: 10px)");
query_should_not_be_parseable("(prefers-color-scheme: dark 0)");
query_should_not_be_parseable("(prefers-color-scheme: dark light)");
query_should_not_be_parseable("(prefers-color-scheme: light/dark)");
test(() => {
let booleanContext = window.matchMedia("(prefers-color-scheme)");
let noPreference = window.matchMedia("(prefers-color-scheme: no-preference)");
assert_equals(booleanContext.matches, !noPreference.matches);
}, "Check that no-preference evaluates to false in the boolean context");
test(() => {
let booleanContext = window.matchMedia("(prefers-color-scheme)");
let noPreference = window.matchMedia("(prefers-color-scheme: no-preference)");
assert_equals(booleanContext.matches, !noPreference.matches);
}, "Check that no-preference evaluates to false in the boolean context");
</script>

View file

@ -0,0 +1,38 @@
<!DOCTYPE html>
<link rel="help" href="https://drafts.csswg.org/mediaqueries-5/#prefers-reduced-motion" />
<script type="text/javascript" src="/resources/testharness.js"></script>
<script type="text/javascript" src="/resources/testharnessreport.js"></script>
<script type="text/javascript" src="resources/matchmedia-utils.js"></script>
<script>
query_should_be_css_parseable("(prefers-reduced-motion)");
query_should_be_css_parseable("(prefers-reduced-motion: no-preference)");
query_should_be_css_parseable("(prefers-reduced-motion: reduce)");
query_should_not_be_css_parseable("(prefers-reduced-motion: 0)");
query_should_not_be_css_parseable("(prefers-reduced-motion: none)");
query_should_not_be_css_parseable("(prefers-reduced-motion: 10px)");
query_should_not_be_css_parseable("(prefers-reduced-motion: no-preference reduce)");
query_should_not_be_css_parseable("(prefers-reduced-motion: reduced)");
query_should_not_be_css_parseable("(prefers-reduced-motion: no-preference/reduce)");
query_should_be_js_parseable("(prefers-reduced-motion)");
query_should_be_js_parseable("(prefers-reduced-motion: no-preference)");
query_should_be_js_parseable("(prefers-reduced-motion: reduce)");
query_should_not_be_js_parseable("(prefers-reduced-motion: 0)");
query_should_not_be_js_parseable("(prefers-reduced-motion: none)");
query_should_not_be_js_parseable("(prefers-reduced-motion: 10px)");
query_should_not_be_js_parseable("(prefers-reduced-motion: no-preference reduce)");
query_should_not_be_js_parseable("(prefers-reduced-motion: reduced)");
query_should_not_be_js_parseable("(prefers-reduced-motion: no-preference/reduce)");
test(() => {
// What this is saying is that 'no-preference' is not the default, so
// irregardless of the current OS settings, (prefers-reduced-motion).matches
// should not be equivalent to (prefers-reduced-motion: no-preference).matches.
let booleanContext = window.matchMedia("(prefers-reduced-motion)");
let noPreference = window.matchMedia("(prefers-reduced-motion: no-preference)");
assert_equals(booleanContext.matches, !noPreference.matches);
}, "Check that no-preference evaluates to false in the boolean context");
</script>

View file

@ -0,0 +1,49 @@
'use strict';
function query_is_css_parseable(query) {
const style = document.createElement('style');
style.type = 'text/css';
document.head.appendChild(style);
const sheet = style.sheet;
try {
sheet.insertRule("@media " + query + "{}", 0);
return sheet.cssRules.length == 1 &&
sheet.cssRules[0].media.mediaText != "not all";
} finally {
while (sheet.cssRules.length)
sheet.deleteRule(0);
style.remove();
}
}
function query_should_be_css_parseable(query) {
test(() => {
assert_true(query_is_css_parseable(query));
}, "Should be parseable in a CSS stylesheet: '" + query + "'");
}
function query_should_not_be_css_parseable(query) {
test(() => {
assert_false(query_is_css_parseable(query));
}, "Should not be parseable in a CSS stylesheet: '" + query + "'");
}
function query_is_js_parseable(query) {
// We cannot rely on whether a given feature is on or off, so only check the
// 'media' member of the result.
const match = window.matchMedia(query);
return match.media == query;
}
function query_should_be_js_parseable(query) {
test(() => {
assert_true(query_is_js_parseable(query));
}, "Should be parseable in JS: '" + query + "'");
}
function query_should_not_be_js_parseable(query) {
test(() => {
assert_false(query_is_js_parseable(query));
}, "Should not be parseable in JS: '" + query + "'");
}

View file

@ -32,6 +32,11 @@
assert_equals(Image.prototype, HTMLImageElement.prototype, "Image.prototype is same as HTMLImageElement.prototype");
assert_equals(new Image().__proto__, HTMLImageElement.prototype, "Image __proto__ is HTMLImageElement prototype ");
assert_equals(Image.prototype.__proto__, HTMLElement.prototype, "Image.prototype __proto__ is HTMLElement prototype");
const desc = Object.getOwnPropertyDescriptor(Image, "prototype");
assert_false(desc.configurable, "Image.prototype is not configurable");
assert_false(desc.enumerable, "Image.prototype is not enumerable");
assert_false(desc.writable, "Image.prototype is not writable");
}, "NamedConstructor creates the correct object structure.");
</script>

View file

@ -1,7 +1,7 @@
// GENERATED CONTENT - DO NOT EDIT
// Content of this file was automatically extracted from the
// "DOM Standard" spec.
// See: https://dom.spec.whatwg.org/
// Content was automatically extracted by Reffy into reffy-reports
// (https://github.com/tidoust/reffy-reports)
// Source: DOM Standard (https://dom.spec.whatwg.org/)
[Constructor(DOMString type, optional EventInit eventInitDict),
Exposed=(Window,Worker,AudioWorklet)]
@ -145,7 +145,7 @@ Text includes Slotable;
interface NodeList {
getter Node? item(unsigned long index);
readonly attribute unsigned long length;
// iterable<Node>;
iterable<Node>;
};
[Exposed=Window, LegacyUnenumerableNamedProperties]
@ -548,5 +548,5 @@ interface DOMTokenList {
[CEReactions] boolean replace(DOMString token, DOMString newToken);
boolean supports(DOMString token);
[CEReactions] stringifier attribute DOMString value;
// iterable<DOMString>;
iterable<DOMString>;
};

View file

@ -22,7 +22,8 @@ partial interface Performance {
void clearMeasures(optional DOMString measureName);
};
[Exposed=(Window,Worker)]
[Exposed=(Window,Worker),
Constructor(DOMString markName, optional PerformanceMarkOptions markOptions)]
interface PerformanceMark : PerformanceEntry {
readonly attribute any detail;
};

View file

@ -0,0 +1,66 @@
<!doctype html>
<html>
<head>
<title>MediaRecorder Pause and Resume</title>
<link rel="help" href="https://w3c.github.io/mediacapture-record/MediaRecorder.html#mediarecorder">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
</head>
<body>
<canvas id="canvas" width="200" height="200">
</canvas>
<script>
function createVideoStream() {
let canvas = document.getElementById("canvas");
canvas.getContext('2d');
return canvas.captureStream();
}
function recordEvents(target, events) {
let arr = [];
for (let ev of events) {
target.addEventListener(ev, _ => arr.push(ev));
}
return arr;
}
promise_test(async () => {
let video = createVideoStream();
let recorder = new MediaRecorder(video);
let events = recordEvents(recorder,
["start", "stop", "dataavailable", "pause", "resume", "error"]);
recorder.start();
assert_equals(recorder.state, "recording", "MediaRecorder has been started successfully");
recorder.pause();
assert_equals(recorder.state, "paused", "MediaRecorder should be paused immediately following pause()");
// A second call to pause should be idempotent
recorder.pause();
assert_equals(recorder.state, "paused", "MediaRecorder should be paused immediately following pause()");
let event = await new Promise(r => recorder.onpause = r);
assert_equals(event.type, "pause", "the event type should be pause");
assert_true(event.isTrusted, "isTrusted should be true when the event is created by C++");
recorder.resume();
assert_equals(recorder.state, "recording", "MediaRecorder state should be recording immediately following resume() call");
// A second call to resume should be idempotent
recorder.resume();
assert_equals(recorder.state, "recording", "MediaRecorder state should be recording immediately following resume() call");
event = await new Promise(r => recorder.onresume = r);
assert_equals(event.type, "resume", "the event type should be resume");
assert_true(event.isTrusted, "isTrusted should be true when the event is created by C++");
recorder.stop();
await new Promise(r => recorder.onstop = r);
assert_array_equals(events, ["start", "pause", "resume", "dataavailable", "stop"],
"Should have gotten expected events");
}, "MediaRecorder handles pause() and resume() calls appropriately in state and events");
</script>
</body>
</html>

View file

@ -16,35 +16,68 @@
return canvas.captureStream();
}
async_test(t => {
function recordEvents(target, events) {
let arr = [];
for (let ev of events) {
target.addEventListener(ev, _ => arr.push(ev));
}
return arr;
}
promise_test(async t => {
let video = createVideoStream();
let recorder = new MediaRecorder(video);
recorder.onstop = t.step_func(errorEvent => {
assert_equals(errorEvent.type, 'stop', 'the error type should be stop');
assert_true(errorEvent.isTrusted, 'isTrusted should be true when the event is created by C++');
assert_equals(recorder.state, "inactive", "MediaRecorder has been stopped when all tracks are ended");
t.done();
});
let events = recordEvents(recorder,
["start", "stop", "dataavailable", "pause", "resume", "error"]);
assert_equals(video.getVideoTracks().length, 1, "video mediastream starts with one track");
recorder.start();
assert_equals(recorder.state, "recording", "MediaRecorder has been started successfully");
video.getVideoTracks()[0].stop();
assert_equals(recorder.state, "recording", "MediaRecorder state should be recording immediately following last track ending");
let event = await new Promise(r => recorder.onstop = r);
assert_equals(event.type, "stop", "the event type should be stop");
assert_true(event.isTrusted, "isTrusted should be true when the event is created by C++");
assert_equals(recorder.state, "inactive", "MediaRecorder is inactive after stop event");
assert_array_equals(events, ["start", "dataavailable", "stop"],
"Should have gotten expected events");
recorder.stop();
await Promise.race([
new Promise((_, reject) => recorder.onstop =
_ => reject(new Error("stop() is idempotent"))),
new Promise(r => t.step_timeout(r, 0))
]);
}, "MediaRecorder will stop recording and fire a stop event when all tracks are ended");
async_test(t => {
promise_test(async t => {
let video = createVideoStream();
let recorder = new MediaRecorder(video);
recorder.onstop = t.step_func(errorEvent => {
assert_equals(errorEvent.type, 'stop', 'the error type should be stop');
assert_true(errorEvent.isTrusted, 'isTrusted should be true when the event is created by C++');
assert_equals(recorder.state, "inactive", "MediaRecorder has been stopped when stop() is called");
t.done();
});
let events = recordEvents(recorder,
["start", "stop", "dataavailable", "pause", "resume", "error"]);
recorder.start();
assert_equals(recorder.state, "recording", "MediaRecorder has been started successfully");
recorder.stop();
assert_equals(recorder.state, "recording", "State should remain the same until stop event is fired");
assert_equals(recorder.state, "inactive", "MediaRecorder state should be inactive immediately following stop() call");
let event = await new Promise (r => recorder.onstop = r);
assert_equals(event.type, "stop", "the event type should be stop");
assert_true(event.isTrusted, "isTrusted should be true when the event is created by C++");
assert_equals(recorder.state, "inactive", "MediaRecorder is inactive after stop event");
assert_array_equals(events, ["start", "dataavailable", "stop"],
"Should have gotten expected events");
recorder.stop();
await Promise.race([
new Promise((_, reject) => recorder.onstop =
_ => reject(new Error("stop() is idempotent"))),
new Promise(r => t.step_timeout(r, 0))
]);
}, "MediaRecorder will stop recording and fire a stop event when stop() is called");
</script>
</body>
</html>
</html>

View file

@ -0,0 +1,16 @@
<!DOCTYPE html>
<html class="reftest-wait">
<title>Portals rendering test</title>
<link rel="match" href="references/portals-rendering.html">
<body>
<portal src="resources/portals-rendering-portal.html" style="background-color: red; width: 100px; height: 100px"></portal>
<script>
var bc = new BroadcastChannel('portal');
bc.onmessage = function(e) {
window.requestAnimationFrame(function(ts) {
document.documentElement.classList.remove('reftest-wait');
});
bc.close();
}
</script>
</body>

View file

@ -0,0 +1,5 @@
<!DOCTYPE html>
<title>Portals rendering test</title>
<body>
<div style="background-color: green; width: 100px; height: 100px">
</body>

View file

@ -0,0 +1,10 @@
<!DOCTYPE html>
<body style="background-color: green">
<script>
window.requestAnimationFrame(function(ts) {
var bc = new BroadcastChannel('portal');
bc.postMessage('loaded');
bc.close();
});
</script>
</body>

View file

@ -2309,21 +2309,6 @@ IdlInterface.prototype.do_member_operation_asserts = function(memberHolderObject
}
}
IdlInterface.prototype.add_iterable_members = function(member)
{
this.members.push(new IdlInterfaceMember(
{ type: "operation", name: "entries", idlType: "iterator", arguments: []}));
this.members.push(new IdlInterfaceMember(
{ type: "operation", name: "keys", idlType: "iterator", arguments: []}));
this.members.push(new IdlInterfaceMember(
{ type: "operation", name: "values", idlType: "iterator", arguments: []}));
this.members.push(new IdlInterfaceMember(
{ type: "operation", name: "forEach", idlType: "void",
arguments:
[{ name: "callback", idlType: {idlType: "function"}},
{ name: "thisValue", idlType: {idlType: "any"}, optional: true}]}));
};
IdlInterface.prototype.test_to_json_operation = function(memberHolderObject, member) {
var instanceName = memberHolderObject && memberHolderObject.constructor.name
|| member.name + " object";
@ -2351,27 +2336,29 @@ IdlInterface.prototype.test_to_json_operation = function(memberHolderObject, mem
IdlInterface.prototype.test_member_iterable = function(member)
{
var isPairIterator = member.idlType.length === 2;
subsetTestByKey(this.name, test, function()
{
var descriptor = Object.getOwnPropertyDescriptor(this.get_interface_object().prototype, Symbol.iterator);
assert_true(descriptor.writable, "property should be writable");
assert_true(descriptor.configurable, "property should be configurable");
assert_false(descriptor.enumerable, "property should not be enumerable");
assert_equals(this.get_interface_object().prototype[Symbol.iterator].name, isPairIterator ? "entries" : "values", "@@iterator function does not have the right name");
}.bind(this), "Testing Symbol.iterator property of iterable interface " + this.name);
var isPairIterator = member.idlType.length === 2;
var proto = this.get_interface_object().prototype;
var descriptor = Object.getOwnPropertyDescriptor(proto, Symbol.iterator);
if (isPairIterator) {
subsetTestByKey(this.name, test, function() {
assert_equals(this.get_interface_object().prototype[Symbol.iterator], this.get_interface_object().prototype["entries"], "entries method is not the same as @@iterator");
}.bind(this), "Testing pair iterable interface " + this.name);
} else {
subsetTestByKey(this.name, test, function() {
["entries", "keys", "values", "forEach", Symbol.Iterator].forEach(function(property) {
assert_equals(this.get_interface_object().prototype[property], Array.prototype[property], property + " function is not the same as Array one");
assert_true(descriptor.writable, "@@iterator property should be writable");
assert_true(descriptor.configurable, "@@iterator property should be configurable");
assert_false(descriptor.enumerable, "@@iterator property should not be enumerable");
assert_equals(typeof descriptor.value, "function", "@@iterator property should be a function");
assert_equals(descriptor.value.length, 0, "@@iterator function object length should be 0");
assert_equals(descriptor.value.name, isPairIterator ? "entries" : "values", "@@iterator function object should have the right name");
if (isPairIterator) {
assert_equals(proto["entries"], proto[Symbol.iterator], "entries method should be the same as @@iterator method");
} else {
assert_equals(proto[Symbol.iterator], Array.prototype[Symbol.iterator], "@@iterator method should be the same as Array prototype's");
["entries", "keys", "values", "forEach", Symbol.iterator].forEach(function(property) {
var propertyName = property === Symbol.iterator ? "@@iterator" : property;
assert_equals(proto[property], Array.prototype[property], propertyName + " method should be the same as Array prototype's");
}.bind(this));
}.bind(this), "Testing value iterable interface " + this.name);
}
}
}.bind(this), this.name + " interface: iterable<" + member.idlType.map(function(t) { return t.idlType; }).join(", ") + ">");
};
IdlInterface.prototype.test_member_stringifier = function(member)
@ -2437,19 +2424,6 @@ IdlInterface.prototype.test_member_stringifier = function(member)
IdlInterface.prototype.test_members = function()
{
for (var i = 0; i < this.members.length; i++)
{
var member = this.members[i];
switch (member.type) {
case "iterable":
this.add_iterable_members(member);
break;
// TODO: add setlike and maplike handling.
default:
break;
}
}
for (var i = 0; i < this.members.length; i++)
{
var member = this.members[i];