Improve CI builds relying on Chrome (#796)
* Use ES6 Proxies to implement collections in the Chrome debugger * rework realm-test-names event * move React stuff on the CPH mac mini * use node with npm3 * remove debugging aid code
This commit is contained in:
parent
35c21c203f
commit
12bde1ed35
|
@ -68,8 +68,8 @@ stage('build') {
|
|||
macos_node_release: doMacBuild('node Release'),
|
||||
macos_realmjs_debug: doMacBuild('realmjs Debug'),
|
||||
macos_realmjs_release: doMacBuild('realmjs Release'),
|
||||
macos_react_tests_debug: doMacBuild('react-tests Debug'),
|
||||
macos_react_tests_release: doMacBuild('react-tests Release'),
|
||||
macos_react_tests_debug: doReactBuild('react-tests Debug'),
|
||||
macos_react_tests_release: doReactBuild('react-tests Release'),
|
||||
macos_react_example_debug: doMacBuild('react-example Debug'),
|
||||
macos_react_example_release: doMacBuild('react-example Release'),
|
||||
android_react_tests: doAndroidBuild('react-tests-android', {
|
||||
|
@ -184,3 +184,18 @@ def doMacBuild(target, postStep = null) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
def doReactBuild(target, postStep = null) {
|
||||
return {
|
||||
node('xamarin-mac') {
|
||||
try {
|
||||
lock("${env.NODE_NAME} iOS Simulator") {
|
||||
doInside("./scripts/test.sh", target, postStep)
|
||||
}
|
||||
} finally {
|
||||
deleteDir()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,8 @@
|
|||
'use strict';
|
||||
|
||||
import { keys } from './constants';
|
||||
import { getterForProperty, setterForProperty } from './util';
|
||||
import { getterForProperty } from './util';
|
||||
import { getProperty, setProperty } from './rpc';
|
||||
|
||||
let mutationListeners = {};
|
||||
|
||||
|
@ -52,9 +53,65 @@ export function fireMutationListeners(realmId) {
|
|||
}
|
||||
}
|
||||
|
||||
function isIndex(propertyName) {
|
||||
return typeof propertyName === 'number' || (typeof propertyName === 'string' && /^\d+$/.test(propertyName));
|
||||
}
|
||||
|
||||
const mutable = Symbol('mutable');
|
||||
|
||||
const traps = {
|
||||
get(collection, property, receiver) {
|
||||
if (isIndex(property)) {
|
||||
return getProperty(collection[keys.realm], collection[keys.id], property);
|
||||
}
|
||||
|
||||
return Reflect.get(collection, property, collection);
|
||||
},
|
||||
set(collection, property, value, receiver) {
|
||||
if (isIndex(property)) {
|
||||
if (!collection[mutable]) {
|
||||
return false;
|
||||
}
|
||||
|
||||
setProperty(collection[keys.realm], collection[keys.id], property, value);
|
||||
|
||||
// If this isn't a primitive value, then it might create a new object in the Realm.
|
||||
if (value && typeof value == 'object') {
|
||||
fireMutationListeners(collection[keys.realm]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return Reflect.set(collection, property, value, collection);
|
||||
},
|
||||
ownKeys(collection) {
|
||||
return Reflect.ownKeys(collection).concat(Array.from({ length: collection.length }, (value, key) => String(key)));
|
||||
},
|
||||
getOwnPropertyDescriptor(collection, property) {
|
||||
if (isIndex(property)) {
|
||||
let descriptor = {
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
writable: collection[mutable]
|
||||
};
|
||||
Reflect.defineProperty(descriptor, "value", { get: () => this.get(collection, property) });
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
return Reflect.getOwnPropertyDescriptor(collection, property);
|
||||
},
|
||||
has(collection, property) {
|
||||
if (isIndex(property)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return Reflect.has(collection, property);
|
||||
}
|
||||
};
|
||||
|
||||
export function createCollection(prototype, realmId, info, _mutable) {
|
||||
let collection = Object.create(prototype);
|
||||
let size;
|
||||
|
||||
Object.defineProperties(collection, {
|
||||
'length': {
|
||||
|
@ -65,65 +122,10 @@ export function createCollection(prototype, realmId, info, _mutable) {
|
|||
},
|
||||
});
|
||||
|
||||
let resize = function(length) {
|
||||
if (length == null) {
|
||||
length = collection.length;
|
||||
}
|
||||
if (length == size) {
|
||||
return; // Nothing has changed.
|
||||
}
|
||||
if (size == null) {
|
||||
size = 0; // This is first pass.
|
||||
}
|
||||
|
||||
let props = {};
|
||||
|
||||
if (length > size) {
|
||||
for (let i = size; i < length; i++) {
|
||||
props[i] = {
|
||||
get: getterForProperty(i),
|
||||
set: setterForProperty(i),
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
};
|
||||
}
|
||||
}
|
||||
else if (length < size) {
|
||||
for (let i = size; i >= length; i--) {
|
||||
delete collection[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Helpfully throw an exception on attempts to set to one past the last index.
|
||||
props[length] = {
|
||||
get: getterForProperty(length),
|
||||
set: setterForProperty(length),
|
||||
configurable: true,
|
||||
};
|
||||
|
||||
Object.defineProperties(collection, props);
|
||||
|
||||
size = length;
|
||||
};
|
||||
|
||||
collection[keys.realm] = realmId;
|
||||
collection[keys.id] = info.id;
|
||||
collection[keys.type] = info.type;
|
||||
collection[mutable] = _mutable;
|
||||
|
||||
resize(info.size);
|
||||
|
||||
addMutationListener(realmId, function listener() {
|
||||
try {
|
||||
resize();
|
||||
} catch (e) {
|
||||
// If the error indicates the collection was deleted, then remove this listener.
|
||||
if (e.message.indexOf('Access to invalidated') == 0) {
|
||||
removeMutationListener(realmId, listener);
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return collection;
|
||||
return new Proxy(collection, traps);
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ export const propTypes = {};
|
|||
'realm',
|
||||
'type',
|
||||
].forEach(function(name) {
|
||||
keys[name] = Symbol();
|
||||
keys[name] = Symbol(name);
|
||||
});
|
||||
|
||||
[
|
||||
|
|
|
@ -224,11 +224,14 @@ cleanup
|
|||
trap cleanup EXIT
|
||||
|
||||
# Use a consistent version of Node if possible.
|
||||
if [ -s "${HOME}/.nvm/nvm.sh" ]; then
|
||||
# shellcheck disable=SC1090
|
||||
. "${HOME}/.nvm/nvm.sh"
|
||||
nvm use 5.12 || true
|
||||
if [ -f "$NVM_DIR/nvm.sh" ]; then
|
||||
. "$NVM_DIR/nvm.sh"
|
||||
elif [ -x "$(command -v brew)" ] && [ -f "$(brew --prefix nvm)/nvm.sh" ]; then
|
||||
# we must be on mac and nvm was installed with brew
|
||||
# TODO: change the mac slaves to use manual nvm installation
|
||||
. "$(brew --prefix nvm)/nvm.sh"
|
||||
fi
|
||||
[[ "$(command -v nvm)" ]] && nvm use 6.5.0 || true
|
||||
|
||||
# Remove cached packages
|
||||
rm -rf ~/.yarn-cache/npm-realm-*
|
||||
|
|
|
@ -125,6 +125,7 @@ extern NSMutableArray *RCTGetModuleClasses(void);
|
|||
JSGlobalContextSetIncludesNativeCallStackWhenReportingExceptions(ctx, false);
|
||||
}
|
||||
|
||||
[self.currentBridge.eventDispatcher sendAppEventWithName:@"realm-test-names" body:nil];
|
||||
NSDictionary *testCaseNames = [self waitForEvent:@"realm-test-names"];
|
||||
NSAssert(testCaseNames.count, @"No test names were provided by the JS");
|
||||
|
||||
|
|
|
@ -26,6 +26,11 @@ RealmTests.registerTests({
|
|||
ListViewTest,
|
||||
});
|
||||
|
||||
// Listen for event signalling native is ready to receive test names
|
||||
NativeAppEventEmitter.addListener('realm-test-names', () => {
|
||||
NativeModules.Realm.emit('realm-test-names', getTestNames());
|
||||
});
|
||||
|
||||
// Listen for event to run a particular test.
|
||||
NativeAppEventEmitter.addListener('realm-run-test', async ({suite, name}) => {
|
||||
let error;
|
||||
|
@ -38,14 +43,6 @@ NativeAppEventEmitter.addListener('realm-run-test', async ({suite, name}) => {
|
|||
NativeModules.Realm.emit('realm-test-finished', error);
|
||||
});
|
||||
|
||||
// Inform the native test harness about the test suite once it's ready.
|
||||
setTimeout(() => {
|
||||
// The emit() method only exists on iOS, for now.
|
||||
if (NativeModules.Realm.emit) {
|
||||
NativeModules.Realm.emit('realm-test-names', getTestNames());
|
||||
}
|
||||
}, 500);
|
||||
|
||||
export function getTestNames() {
|
||||
return RealmTests.getTestNames();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue