mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-11-10 05:08:36 +02:00
***
Bug 1514594: Part 3a - Change ChromeUtils.import to return an exports object; not pollute global. r=mccr8
This changes the behavior of ChromeUtils.import() to return an exports object,
rather than a module global, in all cases except when `null` is passed as a
second argument, and changes the default behavior not to pollute the global
scope with the module's exports. Thus, the following code written for the old
model:
ChromeUtils.import("resource://gre/modules/Services.jsm");
is approximately the same as the following, in the new model:
var {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
Since the two behaviors are mutually incompatible, this patch will land with a
scripted rewrite to update all existing callers to use the new model rather
than the old.
***
Bug 1514594: Part 3b - Mass rewrite all JS code to use the new ChromeUtils.import API. rs=Gijs
This was done using the followng script:
https://bitbucket.org/kmaglione/m-c-rewrites/src/tip/processors/cu-import-exports.jsm
***
Bug 1514594: Part 3c - Update ESLint plugin for ChromeUtils.import API changes. r=Standard8
Differential Revision: https://phabricator.services.mozilla.com/D16747
***
Bug 1514594: Part 3d - Remove/fix hundreds of duplicate imports from sync tests. r=Gijs
Differential Revision: https://phabricator.services.mozilla.com/D16748
***
Bug 1514594: Part 3e - Remove no-op ChromeUtils.import() calls. r=Gijs
Differential Revision: https://phabricator.services.mozilla.com/D16749
***
Bug 1514594: Part 3f.1 - Cleanup various test corner cases after mass rewrite. r=Gijs
***
Bug 1514594: Part 3f.2 - Cleanup various non-test corner cases after mass rewrite. r=Gijs
Differential Revision: https://phabricator.services.mozilla.com/D16750
--HG--
extra : rebase_source : 359574ee3064c90f33bf36c2ebe3159a24cc8895
extra : histedit_source : b93c8f42808b1599f9122d7842d2c0b3e656a594%2C64a3a4e3359dc889e2ab2b49461bab9e27fc10a7
904 lines
22 KiB
JavaScript
904 lines
22 KiB
JavaScript
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
// Ideally this would be an xpcshell test, but Troubleshoot relies on things
|
|
// that aren't initialized outside of a XUL app environment like AddonManager
|
|
// and the "@mozilla.org/xre/app-info;1" component.
|
|
|
|
const {AppConstants} = ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
|
|
const {Troubleshoot} = ChromeUtils.import("resource://gre/modules/Troubleshoot.jsm");
|
|
|
|
function test() {
|
|
waitForExplicitFinish();
|
|
function doNextTest() {
|
|
if (!tests.length) {
|
|
finish();
|
|
return;
|
|
}
|
|
tests.shift()(doNextTest);
|
|
}
|
|
doNextTest();
|
|
}
|
|
|
|
registerCleanupFunction(function() {
|
|
// Troubleshoot.jsm is imported into the global scope -- the window -- above.
|
|
// If it's not deleted, it outlives the test and is reported as a leak.
|
|
delete window.Troubleshoot;
|
|
});
|
|
|
|
var tests = [
|
|
|
|
function snapshotSchema(done) {
|
|
Troubleshoot.snapshot(function(snapshot) {
|
|
try {
|
|
validateObject(snapshot, SNAPSHOT_SCHEMA);
|
|
ok(true, "The snapshot should conform to the schema.");
|
|
} catch (err) {
|
|
ok(false, "Schema mismatch, " + err);
|
|
}
|
|
done();
|
|
});
|
|
},
|
|
|
|
function modifiedPreferences(done) {
|
|
let prefs = [
|
|
"javascript.troubleshoot",
|
|
"troubleshoot.foo",
|
|
"javascript.print_to_filename",
|
|
"network.proxy.troubleshoot",
|
|
];
|
|
prefs.forEach(function(p) {
|
|
Services.prefs.setBoolPref(p, true);
|
|
is(Services.prefs.getBoolPref(p), true, "The pref should be set: " + p);
|
|
});
|
|
Troubleshoot.snapshot(function(snapshot) {
|
|
let p = snapshot.modifiedPreferences;
|
|
is(p["javascript.troubleshoot"], true,
|
|
"The pref should be present because it's whitelisted " +
|
|
"but not blacklisted.");
|
|
ok(!("troubleshoot.foo" in p),
|
|
"The pref should be absent because it's not in the whitelist.");
|
|
ok(!("javascript.print_to_filename" in p),
|
|
"The pref should be absent because it's blacklisted.");
|
|
ok(!("network.proxy.troubleshoot" in p),
|
|
"The pref should be absent because it's blacklisted.");
|
|
prefs.forEach(p => Services.prefs.deleteBranch(p));
|
|
done();
|
|
});
|
|
},
|
|
|
|
function unicodePreferences(done) {
|
|
let name = "font.name.sans-serif.x-western";
|
|
let utf8Value = "\xc4\x8capk\xc5\xafv Krasopis";
|
|
let unicodeValue = "\u010Capk\u016Fv Krasopis";
|
|
|
|
// set/getCharPref work with 8bit strings (utf8)
|
|
Services.prefs.setCharPref(name, utf8Value);
|
|
|
|
Troubleshoot.snapshot(function(snapshot) {
|
|
let p = snapshot.modifiedPreferences;
|
|
is(p[name], unicodeValue, "The pref should have correct Unicode value.");
|
|
Services.prefs.deleteBranch(name);
|
|
done();
|
|
});
|
|
},
|
|
];
|
|
|
|
// This is inspired by JSON Schema, or by the example on its Wikipedia page
|
|
// anyway.
|
|
const SNAPSHOT_SCHEMA = {
|
|
type: "object",
|
|
required: true,
|
|
properties: {
|
|
application: {
|
|
required: true,
|
|
type: "object",
|
|
properties: {
|
|
name: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
version: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
buildID: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
userAgent: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
osVersion: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
vendor: {
|
|
type: "string",
|
|
},
|
|
updateChannel: {
|
|
type: "string",
|
|
},
|
|
supportURL: {
|
|
type: "string",
|
|
},
|
|
launcherProcessState: {
|
|
type: "number",
|
|
},
|
|
remoteAutoStart: {
|
|
type: "boolean",
|
|
required: true,
|
|
},
|
|
autoStartStatus: {
|
|
type: "number",
|
|
},
|
|
numTotalWindows: {
|
|
type: "number",
|
|
},
|
|
numRemoteWindows: {
|
|
type: "number",
|
|
},
|
|
currentContentProcesses: {
|
|
type: "number",
|
|
},
|
|
maxContentProcesses: {
|
|
type: "number",
|
|
},
|
|
policiesStatus: {
|
|
type: "number",
|
|
},
|
|
keyGoogleFound: {
|
|
type: "boolean",
|
|
},
|
|
keyMozillaFound: {
|
|
type: "boolean",
|
|
},
|
|
safeMode: {
|
|
type: "boolean",
|
|
},
|
|
},
|
|
},
|
|
crashes: {
|
|
required: false,
|
|
type: "object",
|
|
properties: {
|
|
pending: {
|
|
required: true,
|
|
type: "number",
|
|
},
|
|
submitted: {
|
|
required: true,
|
|
type: "array",
|
|
items: {
|
|
type: "object",
|
|
properties: {
|
|
id: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
date: {
|
|
required: true,
|
|
type: "number",
|
|
},
|
|
pending: {
|
|
required: true,
|
|
type: "boolean",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
extensions: {
|
|
required: true,
|
|
type: "array",
|
|
items: {
|
|
type: "object",
|
|
properties: {
|
|
name: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
version: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
id: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
isActive: {
|
|
required: true,
|
|
type: "boolean",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
securitySoftware: {
|
|
required: false,
|
|
type: "object",
|
|
properties: {
|
|
registeredAntiVirus: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
registeredAntiSpyware: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
registeredFirewall: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
},
|
|
},
|
|
features: {
|
|
required: true,
|
|
type: "array",
|
|
items: {
|
|
type: "object",
|
|
properties: {
|
|
name: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
version: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
id: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
modifiedPreferences: {
|
|
required: true,
|
|
type: "object",
|
|
},
|
|
lockedPreferences: {
|
|
required: true,
|
|
type: "object",
|
|
},
|
|
graphics: {
|
|
required: true,
|
|
type: "object",
|
|
properties: {
|
|
numTotalWindows: {
|
|
required: true,
|
|
type: "number",
|
|
},
|
|
numAcceleratedWindows: {
|
|
required: true,
|
|
type: "number",
|
|
},
|
|
windowLayerManagerType: {
|
|
type: "string",
|
|
},
|
|
windowLayerManagerRemote: {
|
|
type: "boolean",
|
|
},
|
|
windowUsingAdvancedLayers: {
|
|
type: "boolean",
|
|
},
|
|
numAcceleratedWindowsMessage: {
|
|
type: "object",
|
|
properties: {
|
|
key: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
args: {
|
|
required: false,
|
|
type: "object",
|
|
},
|
|
},
|
|
},
|
|
adapterDescription: {
|
|
type: "string",
|
|
},
|
|
adapterVendorID: {
|
|
type: "string",
|
|
},
|
|
adapterDeviceID: {
|
|
type: "string",
|
|
},
|
|
adapterSubsysID: {
|
|
type: "string",
|
|
},
|
|
adapterRAM: {
|
|
type: "string",
|
|
},
|
|
adapterDrivers: {
|
|
type: "string",
|
|
},
|
|
driverVersion: {
|
|
type: "string",
|
|
},
|
|
driverDate: {
|
|
type: "string",
|
|
},
|
|
adapterDescription2: {
|
|
type: "string",
|
|
},
|
|
adapterVendorID2: {
|
|
type: "string",
|
|
},
|
|
adapterDeviceID2: {
|
|
type: "string",
|
|
},
|
|
adapterSubsysID2: {
|
|
type: "string",
|
|
},
|
|
adapterRAM2: {
|
|
type: "string",
|
|
},
|
|
adapterDrivers2: {
|
|
type: "string",
|
|
},
|
|
driverVersion2: {
|
|
type: "string",
|
|
},
|
|
driverDate2: {
|
|
type: "string",
|
|
},
|
|
isGPU2Active: {
|
|
type: "boolean",
|
|
},
|
|
direct2DEnabled: {
|
|
type: "boolean",
|
|
},
|
|
directWriteEnabled: {
|
|
type: "boolean",
|
|
},
|
|
directWriteVersion: {
|
|
type: "string",
|
|
},
|
|
usesTiling: {
|
|
type: "boolean",
|
|
},
|
|
contentUsesTiling: {
|
|
type: "boolean",
|
|
},
|
|
offMainThreadPaintEnabled: {
|
|
type: "boolean",
|
|
},
|
|
offMainThreadPaintWorkerCount: {
|
|
type: "number",
|
|
},
|
|
clearTypeParameters: {
|
|
type: "string",
|
|
},
|
|
webgl1Renderer: {
|
|
type: "string",
|
|
},
|
|
webgl1Version: {
|
|
type: "string",
|
|
},
|
|
webgl1DriverExtensions: {
|
|
type: "string",
|
|
},
|
|
webgl1Extensions: {
|
|
type: "string",
|
|
},
|
|
webgl1WSIInfo: {
|
|
type: "string",
|
|
},
|
|
webgl2Renderer: {
|
|
type: "string",
|
|
},
|
|
webgl2Version: {
|
|
type: "string",
|
|
},
|
|
webgl2DriverExtensions: {
|
|
type: "string",
|
|
},
|
|
webgl2Extensions: {
|
|
type: "string",
|
|
},
|
|
webgl2WSIInfo: {
|
|
type: "string",
|
|
},
|
|
info: {
|
|
type: "object",
|
|
},
|
|
failures: {
|
|
type: "object",
|
|
properties: {
|
|
key: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
args: {
|
|
required: false,
|
|
type: "object",
|
|
},
|
|
},
|
|
},
|
|
indices: {
|
|
type: "array",
|
|
items: {
|
|
type: "number",
|
|
},
|
|
},
|
|
featureLog: {
|
|
type: "object",
|
|
},
|
|
crashGuards: {
|
|
type: "array",
|
|
},
|
|
direct2DEnabledMessage: {
|
|
type: "object",
|
|
properties: {
|
|
key: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
args: {
|
|
required: false,
|
|
type: "object",
|
|
},
|
|
},
|
|
},
|
|
lowEndMachine: {
|
|
type: "boolean",
|
|
},
|
|
targetFrameRate: {
|
|
type: "number",
|
|
},
|
|
},
|
|
},
|
|
media: {
|
|
required: true,
|
|
type: "object",
|
|
properties: {
|
|
currentAudioBackend: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
currentMaxAudioChannels: {
|
|
required: true,
|
|
type: "number",
|
|
},
|
|
currentPreferredSampleRate: {
|
|
required: true,
|
|
type: "number",
|
|
},
|
|
audioOutputDevices: {
|
|
required: true,
|
|
type: "array",
|
|
items: {
|
|
type: "object",
|
|
properties: {
|
|
name: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
groupId: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
vendor: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
type: {
|
|
required: true,
|
|
type: "number",
|
|
},
|
|
state: {
|
|
required: true,
|
|
type: "number",
|
|
},
|
|
preferred: {
|
|
required: true,
|
|
type: "number",
|
|
},
|
|
supportedFormat: {
|
|
required: true,
|
|
type: "number",
|
|
},
|
|
defaultFormat: {
|
|
required: true,
|
|
type: "number",
|
|
},
|
|
maxChannels: {
|
|
required: true,
|
|
type: "number",
|
|
},
|
|
defaultRate: {
|
|
required: true,
|
|
type: "number",
|
|
},
|
|
maxRate: {
|
|
required: true,
|
|
type: "number",
|
|
},
|
|
minRate: {
|
|
required: true,
|
|
type: "number",
|
|
},
|
|
maxLatency: {
|
|
required: true,
|
|
type: "number",
|
|
},
|
|
minLatency: {
|
|
required: true,
|
|
type: "number",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
audioInputDevices: {
|
|
required: true,
|
|
type: "array",
|
|
items: {
|
|
type: "object",
|
|
properties: {
|
|
name: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
groupId: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
vendor: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
type: {
|
|
required: true,
|
|
type: "number",
|
|
},
|
|
state: {
|
|
required: true,
|
|
type: "number",
|
|
},
|
|
preferred: {
|
|
required: true,
|
|
type: "number",
|
|
},
|
|
supportedFormat: {
|
|
required: true,
|
|
type: "number",
|
|
},
|
|
defaultFormat: {
|
|
required: true,
|
|
type: "number",
|
|
},
|
|
maxChannels: {
|
|
required: true,
|
|
type: "number",
|
|
},
|
|
defaultRate: {
|
|
required: true,
|
|
type: "number",
|
|
},
|
|
maxRate: {
|
|
required: true,
|
|
type: "number",
|
|
},
|
|
minRate: {
|
|
required: true,
|
|
type: "number",
|
|
},
|
|
maxLatency: {
|
|
required: true,
|
|
type: "number",
|
|
},
|
|
minLatency: {
|
|
required: true,
|
|
type: "number",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
javaScript: {
|
|
required: true,
|
|
type: "object",
|
|
properties: {
|
|
incrementalGCEnabled: {
|
|
type: "boolean",
|
|
},
|
|
},
|
|
},
|
|
accessibility: {
|
|
required: true,
|
|
type: "object",
|
|
properties: {
|
|
isActive: {
|
|
required: true,
|
|
type: "boolean",
|
|
},
|
|
forceDisabled: {
|
|
type: "number",
|
|
},
|
|
handlerUsed: {
|
|
type: "boolean",
|
|
},
|
|
instantiator: {
|
|
type: "string",
|
|
},
|
|
},
|
|
},
|
|
libraryVersions: {
|
|
required: true,
|
|
type: "object",
|
|
properties: {
|
|
NSPR: {
|
|
required: true,
|
|
type: "object",
|
|
properties: {
|
|
minVersion: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
version: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
},
|
|
},
|
|
NSS: {
|
|
required: true,
|
|
type: "object",
|
|
properties: {
|
|
minVersion: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
version: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
},
|
|
},
|
|
NSSUTIL: {
|
|
required: true,
|
|
type: "object",
|
|
properties: {
|
|
minVersion: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
version: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
},
|
|
},
|
|
NSSSSL: {
|
|
required: true,
|
|
type: "object",
|
|
properties: {
|
|
minVersion: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
version: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
},
|
|
},
|
|
NSSSMIME: {
|
|
required: true,
|
|
type: "object",
|
|
properties: {
|
|
minVersion: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
version: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
userJS: {
|
|
required: true,
|
|
type: "object",
|
|
properties: {
|
|
exists: {
|
|
required: true,
|
|
type: "boolean",
|
|
},
|
|
},
|
|
},
|
|
sandbox: {
|
|
required: false,
|
|
type: "object",
|
|
properties: {
|
|
hasSeccompBPF: {
|
|
required: AppConstants.platform == "linux",
|
|
type: "boolean",
|
|
},
|
|
hasSeccompTSync: {
|
|
required: AppConstants.platform == "linux",
|
|
type: "boolean",
|
|
},
|
|
hasUserNamespaces: {
|
|
required: AppConstants.platform == "linux",
|
|
type: "boolean",
|
|
},
|
|
hasPrivilegedUserNamespaces: {
|
|
required: AppConstants.platform == "linux",
|
|
type: "boolean",
|
|
},
|
|
canSandboxContent: {
|
|
required: false,
|
|
type: "boolean",
|
|
},
|
|
canSandboxMedia: {
|
|
required: false,
|
|
type: "boolean",
|
|
},
|
|
contentSandboxLevel: {
|
|
required: AppConstants.MOZ_CONTENT_SANDBOX,
|
|
type: "number",
|
|
},
|
|
effectiveContentSandboxLevel: {
|
|
required: AppConstants.MOZ_CONTENT_SANDBOX,
|
|
type: "number",
|
|
},
|
|
syscallLog: {
|
|
required: AppConstants.platform == "linux",
|
|
type: "array",
|
|
items: {
|
|
type: "object",
|
|
properties: {
|
|
index: {
|
|
required: true,
|
|
type: "number",
|
|
},
|
|
pid: {
|
|
required: true,
|
|
type: "number",
|
|
},
|
|
tid: {
|
|
required: true,
|
|
type: "number",
|
|
},
|
|
procType: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
syscall: {
|
|
required: true,
|
|
type: "number",
|
|
},
|
|
args: {
|
|
required: true,
|
|
type: "array",
|
|
items: {
|
|
type: "string",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
intl: {
|
|
required: true,
|
|
type: "object",
|
|
properties: {
|
|
localeService: {
|
|
required: true,
|
|
type: "object",
|
|
properties: {
|
|
requested: {
|
|
required: true,
|
|
type: "array",
|
|
},
|
|
available: {
|
|
required: true,
|
|
type: "array",
|
|
},
|
|
supported: {
|
|
required: true,
|
|
type: "array",
|
|
},
|
|
regionalPrefs: {
|
|
required: true,
|
|
type: "array",
|
|
},
|
|
defaultLocale: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
},
|
|
},
|
|
osPrefs: {
|
|
required: true,
|
|
type: "object",
|
|
properties: {
|
|
systemLocales: {
|
|
required: true,
|
|
type: "array",
|
|
},
|
|
regionalPrefsLocales: {
|
|
required: true,
|
|
type: "array",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
};
|
|
|
|
/**
|
|
* Throws an Error if obj doesn't conform to schema. That way you get a nice
|
|
* error message and a stack to help you figure out what went wrong, which you
|
|
* wouldn't get if this just returned true or false instead. There's still
|
|
* room for improvement in communicating validation failures, however.
|
|
*
|
|
* @param obj The object to validate.
|
|
* @param schema The schema that obj should conform to.
|
|
*/
|
|
function validateObject(obj, schema) {
|
|
if (obj === undefined && !schema.required)
|
|
return;
|
|
if (typeof(schema.type) != "string")
|
|
throw schemaErr("'type' must be a string", schema);
|
|
if (objType(obj) != schema.type)
|
|
throw validationErr("Object is not of the expected type", obj, schema);
|
|
let validatorFnName = "validateObject_" + schema.type;
|
|
if (!(validatorFnName in this))
|
|
throw schemaErr("Validator function not defined for type", schema);
|
|
this[validatorFnName](obj, schema);
|
|
}
|
|
|
|
function validateObject_object(obj, schema) {
|
|
if (typeof(schema.properties) != "object")
|
|
// Don't care what obj's properties are.
|
|
return;
|
|
// First check that all the schema's properties match the object.
|
|
for (let prop in schema.properties)
|
|
validateObject(obj[prop], schema.properties[prop]);
|
|
// Now check that the object doesn't have any properties not in the schema.
|
|
for (let prop in obj)
|
|
if (!(prop in schema.properties))
|
|
throw validationErr("Object has property " + prop + " not in schema", obj, schema);
|
|
}
|
|
|
|
function validateObject_array(array, schema) {
|
|
if (typeof(schema.items) != "object")
|
|
// Don't care what the array's elements are.
|
|
return;
|
|
array.forEach(elt => validateObject(elt, schema.items));
|
|
}
|
|
|
|
function validateObject_string(str, schema) {}
|
|
function validateObject_boolean(bool, schema) {}
|
|
function validateObject_number(num, schema) {}
|
|
|
|
function validationErr(msg, obj, schema) {
|
|
return new Error("Validation error: " + msg +
|
|
": object=" + JSON.stringify(obj) +
|
|
", schema=" + JSON.stringify(schema));
|
|
}
|
|
|
|
function schemaErr(msg, schema) {
|
|
return new Error("Schema error: " + msg + ": " + JSON.stringify(schema));
|
|
}
|
|
|
|
function objType(obj) {
|
|
let type = typeof(obj);
|
|
if (type != "object")
|
|
return type;
|
|
if (Array.isArray(obj))
|
|
return "array";
|
|
if (obj === null)
|
|
return "null";
|
|
return type;
|
|
}
|