# HG changeset patch # User Frank-Rainer Grahl # Date 1674512195 -3600 # Parent 050945bc9beb998f32c358327e9948214ad42f5e Bug 1371065 - Rip out misc stuff from add-on sdk. r=me a=me SeaMonkey release branch version. Test removal and non packaged stuff only. diff --git a/addon-sdk/Makefile.in b/addon-sdk/Makefile.in deleted file mode 100644 --- a/addon-sdk/Makefile.in +++ /dev/null @@ -1,10 +0,0 @@ -# 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/. - -include $(topsrcdir)/config/rules.mk - -# This can switch to just zipping the files when native jetpacks land -%.xpi: FORCE - $(PYTHON) $(srcdir)/source/bin/cfx xpi --no-strip-xpi --pkgdir=$(ADDONSRC)/$* --output-file=$@ - diff --git a/addon-sdk/mach_commands.py b/addon-sdk/mach_commands.py deleted file mode 100644 --- a/addon-sdk/mach_commands.py +++ /dev/null @@ -1,107 +0,0 @@ -# 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/. - -# Integrates the xpcshell test runner with mach. - -from __future__ import absolute_import - -import os - -import mozpack.path as mozpath - -from mozbuild.base import ( - MachCommandBase, -) - -from mach.decorators import ( - CommandArgument, - CommandProvider, - Command, -) - -@CommandProvider -class MachCommands(MachCommandBase): - @Command('generate-addon-sdk-moz-build', category='misc', - description='Generates the moz.build file for the addon-sdk/ directory.') - def run_addon_sdk_moz_build(self, **params): - addon_sdk_dir = mozpath.join(self.topsrcdir, 'addon-sdk') - js_src_dir = mozpath.join(addon_sdk_dir, 'source/lib') - dirs_to_files = {} - - for path, dirs, files in os.walk(js_src_dir): - js_files = [f for f in files if f.endswith(('.js', '.jsm', '.html'))] - if not js_files: - continue - - relative = mozpath.relpath(path, js_src_dir) - dirs_to_files[relative] = js_files - - moz_build = """# AUTOMATICALLY GENERATED FROM mozbuild.template AND mach. DO NOT EDIT. -# 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/. - -%(moz-build-template)s -if CONFIG['MOZ_WIDGET_TOOLKIT'] != "gonk": -%(non-b2g-modules)s -%(always-on-modules)s""" - - non_b2g_paths = [ - 'method/test', - 'sdk/ui', - 'sdk/ui/button', - 'sdk/ui/sidebar', - 'sdk/places', - 'sdk/places/host', - 'sdk/tabs', - 'sdk/panel', - 'sdk/frame', - 'sdk/test', - 'sdk/window', - 'sdk/windows', - 'sdk/deprecated', - ] - - non_b2g_modules = [] - always_on_modules = [] - - for d, files in sorted(dirs_to_files.items()): - if d in non_b2g_paths: - non_b2g_modules.append((d, files)) - else: - always_on_modules.append((d, files)) - - def list_to_js_modules(l, indent=''): - js_modules = [] - for d, files in l: - if d == '': - module_path = '' - dir_path = '' - else: - # Ensure that we don't have things like: - # EXTRA_JS_MODULES.commonjs.sdk.private-browsing - # which would be a Python syntax error. - path = d.split('/') - module_path = ''.join('.' + p if p.find('-') == -1 else "['%s']" % p for p in path) - dir_path = d + '/' - filelist = ["'source/lib/%s%s'" % (dir_path, f) - for f in sorted(files, key=lambda x: x.lower())] - js_modules.append("EXTRA_JS_MODULES.commonjs%s += [\n %s,\n]\n" - % (module_path, ',\n '.join(filelist))) - stringified = '\n'.join(js_modules) - # This isn't the same thing as |js_modules|, since |js_modules| had - # embedded newlines. - lines = stringified.split('\n') - # Indent lines while avoiding trailing whitespace. - lines = [indent + line if line else line for line in lines] - return '\n'.join(lines) - - moz_build_output = mozpath.join(addon_sdk_dir, 'moz.build') - moz_build_template = mozpath.join(addon_sdk_dir, 'mozbuild.template') - with open(moz_build_output, 'w') as f, open(moz_build_template, 'r') as t: - substs = { 'moz-build-template': t.read(), - 'non-b2g-modules': list_to_js_modules(non_b2g_modules, - indent=' '), - 'always-on-modules': list_to_js_modules(always_on_modules) } - f.write(moz_build % substs) diff --git a/addon-sdk/mozbuild.template b/addon-sdk/mozbuild.template deleted file mode 100644 --- a/addon-sdk/mozbuild.template +++ /dev/null @@ -1,16 +0,0 @@ -# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- -# vim: set filetype=python: -# 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/. - -# Makefile.in uses a misc target through test_addons_TARGET. -HAS_MISC_RULE = True - -EXTRA_JS_MODULES.sdk += [ - 'source/app-extension/bootstrap.js', -] - -EXTRA_JS_MODULES.sdk.system += [ - 'source/modules/system/Startup.js', -] diff --git a/addon-sdk/source/.gitattributes b/addon-sdk/source/.gitattributes deleted file mode 100644 --- a/addon-sdk/source/.gitattributes +++ /dev/null @@ -1,5 +0,0 @@ -.gitignore export-ignore -.hgignore export-ignore -.hgtags export-ignore -.gitattributes export-ignore -python-lib/cuddlefish/_version.py export-subst diff --git a/addon-sdk/source/.gitignore b/addon-sdk/source/.gitignore deleted file mode 100644 --- a/addon-sdk/source/.gitignore +++ /dev/null @@ -1,14 +0,0 @@ -local.json -python-lib/cuddlefish/app-extension/components/jetpack.xpt -testdocs.tgz -jetpack-sdk-docs.tgz -.test_tmp -jetpack-sdk-docs -node_modules - -# These should really be in a global .gitignore, but such a thing -# seems ridiculously confusing to set up, so we'll include some -# common intermediate files here. -*.pyc -*~ -*.DS_Store diff --git a/addon-sdk/source/.hgignore b/addon-sdk/source/.hgignore deleted file mode 100644 --- a/addon-sdk/source/.hgignore +++ /dev/null @@ -1,15 +0,0 @@ -syntax: glob -local.json -python-lib/cuddlefish/app-extension/components/jetpack.xpt -testdocs.tgz -jetpack-sdk-docs.tgz -.test_tmp -jetpack-sdk-docs -node_modules - -# These should really be in a global .hgignore, but such a thing -# seems ridiculously confusing to set up, so we'll include some -# common intermediate files here. -*.pyc -*~ -*.DS_Store diff --git a/addon-sdk/source/.jpmignore b/addon-sdk/source/.jpmignore deleted file mode 100644 --- a/addon-sdk/source/.jpmignore +++ /dev/null @@ -1,18 +0,0 @@ -local.json -mapping.json -CONTRIBUTING.md -@addon-sdk.xpi -.* -app-extension/ -bin/ -modules/ -node_modules/ -examples/ -cache/ - -# Python -python-lib/ -*.pyc - -# Windows -*Thumbs.db diff --git a/addon-sdk/source/.travis.yml b/addon-sdk/source/.travis.yml deleted file mode 100644 --- a/addon-sdk/source/.travis.yml +++ /dev/null @@ -1,26 +0,0 @@ -sudo: false -language: node_js -node_js: - - "0.12" - -env: - - JPM_FX_DEBUG=0 - - JPM_FX_DEBUG=1 - -notifications: - irc: "irc.mozilla.org#jetpack" - -cache: - directories: - - cache - -before_install: - - "export DISPLAY=:99.0" - - "/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -ac -screen 0 1280x1024x16 -extension RANDR" - -before_script: - - npm install fx-download -g - - npm install gulp -g - - bash bin/fx-download.sh - - export JPM_FIREFOX_BINARY=$TRAVIS_BUILD_DIR/../firefox/firefox - - cd $TRAVIS_BUILD_DIR diff --git a/addon-sdk/source/CONTRIBUTING.md b/addon-sdk/source/CONTRIBUTING.md deleted file mode 100644 --- a/addon-sdk/source/CONTRIBUTING.md +++ /dev/null @@ -1,54 +0,0 @@ -## Overview - -- Changes should follow the [design guidelines], as well as the [coding style guide] -- All changes need tests -- In order to land, changes need a review by one of the Jetpack reviewers -- Changes may need an API review -- Changes may need a review from a Mozilla platform domain-expert - -If you have questions, ask in [#jetpack on IRC][jetpack irc channel] or on the [Jetpack mailing list]. - -## How to Make Code Contributions - -Follow the [standard mozilla contribution guidelines](https://developer.mozilla.org/en-US/docs/Mozilla/Developer_guide/Introduction). All contributions and patches should be through Bugzilla. - -Pull requests on github are not accepted and new pull requests on github will be rejected. - -## Good First Bugs - -There is a list of [good first bugs here][good first bugs]. - -## Reviewers - -Changes should be reviewed by someone on the [add-on sdk review team](https://bugzilla.mozilla.org/page.cgi?id=review_suggestions.html#Add-on%20SDK) within Bugzilla. - -Others who might be able to help include: - -- [@mossop] -- [@gozala] -- [@ZER0] -- [@jsantell] -- [@zombie] - -For review of Mozilla platform usage and best practices, ask [@autonome], -[@0c0w3], or [@mossop] to find the domain expert. - -For API and developer ergonomics review, ask [@gozala]. - -[design guidelines]:https://wiki.mozilla.org/Labs/Jetpack/Design_Guidelines -[jetpack irc channel]:irc://irc.mozilla.org/#jetpack -[Jetpack mailing list]:http://groups.google.com/group/mozilla-labs-jetpack -[open bugs]:https://bugzilla.mozilla.org/buglist.cgi?quicksearch=product%3ASDK -[make bug]:https://bugzilla.mozilla.org/enter_bug.cgi?product=Add-on%20SDK&component=general -[test intro]:https://developer.mozilla.org/en-US/Add-ons/SDK/Tutorials/Unit_testing -[test API]:https://developer.mozilla.org/en-US/Add-ons/SDK/Low-Level_APIs/test_assert -[coding style guide]:https://github.com/mozilla/addon-sdk/wiki/Coding-style-guide -[Add-on SDK repo]:https://github.com/mozilla/addon-sdk -[GitHub]:https://github.com/ -[good first bugs]:https://bugzilla.mozilla.org/buglist.cgi?list_id=7345714&columnlist=bug_severity%2Cpriority%2Cassigned_to%2Cbug_status%2Ctarget_milestone%2Cresolution%2Cshort_desc%2Cchangeddate&query_based_on=jetpack-good-1st-bugs&status_whiteboard_type=allwordssubstr&query_format=advanced&status_whiteboard=[good%20first%20bug]&bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&bug_status=VERIFIED&product=Add-on%20SDK&known_name=jetpack-good-1st-bugs - -[@mossop]:https://github.com/mossop/ -[@gozala]:https://github.com/Gozala/ -[@ZER0]:https://github.com/ZER0/ -[@jsantell]:https://github.com/jsantell -[@zombie]:https://github.com/zombie diff --git a/addon-sdk/source/LICENSE b/addon-sdk/source/LICENSE deleted file mode 100644 --- a/addon-sdk/source/LICENSE +++ /dev/null @@ -1,30 +0,0 @@ -The files which make up the SDK are developed by Mozilla and licensed -under the MPL 2.0 (http://mozilla.org/MPL/2.0/), with the exception of the -components listed below, which are made available by their authors under -the licenses listed alongside. - -syntaxhighlighter ------------------- -doc/static-files/syntaxhighlighter -Made available under the MIT license. - -jQuery ------- -examples/reddit-panel/data/jquery-1.4.4.min.js -examples/annotator/data/jquery-1.4.2.min.js -Made available under the MIT license. - -simplejson ----------- -python-lib/simplejson -Made available under the MIT license. - -Python Markdown ---------------- -python-lib/markdown -Made available under the BSD license. - -LibraryDetector ---------------- -examples/library-detector/data/library-detector.js -Made available under the MIT license. diff --git a/addon-sdk/source/README.md b/addon-sdk/source/README.md deleted file mode 100644 --- a/addon-sdk/source/README.md +++ /dev/null @@ -1,34 +0,0 @@ -# Mozilla Add-on SDK [![Build Status](https://travis-ci.org/mozilla/addon-sdk.png)](https://travis-ci.org/mozilla/addon-sdk) - -We suggest that developers of new add-ons [should look at using WebExtensions](https://developer.mozilla.org/en-US/Add-ons/WebExtensions). - -Using the Add-on SDK you can create Firefox add-ons using standard Web technologies: JavaScript, HTML, and CSS. The SDK includes JavaScript APIs which you can use to create add-ons, and tools for creating, running, testing, and packaging add-ons. - -If you find a problem, please [report the bug here](https://bugzilla.mozilla.org/enter_bug.cgi?product=Add-on%20SDK). - -## Developing Add-ons - -These resources offer some help: - -* [Add-on SDK Documentation](https://developer.mozilla.org/en-US/Add-ons/SDK) -* [Community Developed Modules](https://github.com/mozilla/addon-sdk/wiki/Community-developed-modules) -* [Jetpack FAQ](https://wiki.mozilla.org/Jetpack/FAQ) -* [StackOverflow Questions](http://stackoverflow.com/questions/tagged/firefox-addon-sdk) -* [Mailing List](https://wiki.mozilla.org/Jetpack#Mailing_list) -* #jetpack on irc.mozilla.org - -## Contributing Code - -Please read these two guides if you wish to make some patches to the addon-sdk: - -* [Contribute Guide](https://github.com/mozilla/addon-sdk/blob/master/CONTRIBUTING.md) -* [Style Guide](https://github.com/mozilla/addon-sdk/wiki/Coding-style-guide) - -## Issues - -We use [bugzilla](https://bugzilla.mozilla.org/) as our issue tracker, here are some useful links: - -* [File a bug](https://bugzilla.mozilla.org/enter_bug.cgi?product=Add-on%20SDK) -* [Open bugs](https://bugzilla.mozilla.org/buglist.cgi?bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&columnlist=bug_severity%2Cpriority%2Cassigned_to%2Cbug_status%2Ctarget_milestone%2Cresolution%2Cshort_desc%2Cchangeddate&product=Add-on%20SDK&query_format=advanced&order=priority) -* [Good first bugs](https://bugzilla.mozilla.org/buglist.cgi?status_whiteboard=[good+first+bug]&&resolution=---&product=Add-on+SDK) -* [Good next bugs](https://bugzilla.mozilla.org/buglist.cgi?status_whiteboard=[good+next+bug]&&resolution=---&product=Add-on+SDK) diff --git a/addon-sdk/source/app-extension/application.ini b/addon-sdk/source/app-extension/application.ini deleted file mode 100644 --- a/addon-sdk/source/app-extension/application.ini +++ /dev/null @@ -1,11 +0,0 @@ -[App] -Vendor=Varma -Name=Test App -Version=1.0 -BuildID=20060101 -Copyright=Copyright (c) 2009 Atul Varma -ID=xulapp@toolness.com - -[Gecko] -MinVersion=1.9.2.0 -MaxVersion=2.0.* diff --git a/addon-sdk/source/app-extension/bootstrap.js b/addon-sdk/source/app-extension/bootstrap.js deleted file mode 100644 --- a/addon-sdk/source/app-extension/bootstrap.js +++ /dev/null @@ -1,362 +0,0 @@ -/* 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/. */ - -// @see http://dxr.mozilla.org/mozilla-central/source/js/src/xpconnect/loader/mozJSComponentLoader.cpp - -'use strict'; - -// IMPORTANT: Avoid adding any initialization tasks here, if you need to do -// something before add-on is loaded consider addon/runner module instead! - -const { classes: Cc, Constructor: CC, interfaces: Ci, utils: Cu, - results: Cr, manager: Cm } = Components; -const ioService = Cc['@mozilla.org/network/io-service;1']. - getService(Ci.nsIIOService); -const resourceHandler = ioService.getProtocolHandler('resource'). - QueryInterface(Ci.nsIResProtocolHandler); -const systemPrincipal = CC('@mozilla.org/systemprincipal;1', 'nsIPrincipal')(); -const scriptLoader = Cc['@mozilla.org/moz/jssubscript-loader;1']. - getService(Ci.mozIJSSubScriptLoader); -const prefService = Cc['@mozilla.org/preferences-service;1']. - getService(Ci.nsIPrefService). - QueryInterface(Ci.nsIPrefBranch); -const appInfo = Cc["@mozilla.org/xre/app-info;1"]. - getService(Ci.nsIXULAppInfo); -const vc = Cc["@mozilla.org/xpcom/version-comparator;1"]. - getService(Ci.nsIVersionComparator); - -const { NetUtil } = Cu.import("resource://gre/modules/NetUtil.jsm", {}); - -const Startup = Cu.import("resource://gre/modules/sdk/system/Startup.js", {}).exports; - - -const REASON = [ 'unknown', 'startup', 'shutdown', 'enable', 'disable', - 'install', 'uninstall', 'upgrade', 'downgrade' ]; - -const bind = Function.call.bind(Function.bind); - -var loader = null; -var unload = null; -var cuddlefishSandbox = null; -var nukeTimer = null; - -var resourceDomains = []; -function setResourceSubstitution(domain, uri) { - resourceDomains.push(domain); - resourceHandler.setSubstitution(domain, uri); -} - -// Utility function that synchronously reads local resource from the given -// `uri` and returns content string. -function readURI(uri) { - let channel = NetUtil.newChannel({ - uri: NetUtil.newURI(uri, 'UTF-8'), - loadUsingSystemPrincipal: true - }); - - let stream = channel.open2(); - - let cstream = Cc['@mozilla.org/intl/converter-input-stream;1']. - createInstance(Ci.nsIConverterInputStream); - cstream.init(stream, 'UTF-8', 0, 0); - - let str = {}; - let data = ''; - let read = 0; - do { - read = cstream.readString(0xffffffff, str); - data += str.value; - } while (read != 0); - - cstream.close(); - - return data; -} - -// We don't do anything on install & uninstall yet, but in a future -// we should allow add-ons to cleanup after uninstall. -function install(data, reason) {} -function uninstall(data, reason) {} - -function startup(data, reasonCode) { - try { - let reason = REASON[reasonCode]; - // URI for the root of the XPI file. - // 'jar:' URI if the addon is packed, 'file:' URI otherwise. - // (Used by l10n module in order to fetch `locale` folder) - let rootURI = data.resourceURI.spec; - - // TODO: Maybe we should perform read harness-options.json asynchronously, - // since we can't do anything until 'sessionstore-windows-restored' anyway. - let options = JSON.parse(readURI(rootURI + './harness-options.json')); - - let id = options.jetpackID; - let name = options.name; - - // Clean the metadata - options.metadata[name]['permissions'] = options.metadata[name]['permissions'] || {}; - - // freeze the permissionss - Object.freeze(options.metadata[name]['permissions']); - // freeze the metadata - Object.freeze(options.metadata[name]); - - // Register a new resource 'domain' for this addon which is mapping to - // XPI's `resources` folder. - // Generate the domain name by using jetpack ID, which is the extension ID - // by stripping common characters that doesn't work as a domain name: - let uuidRe = - /^\{([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\}$/; - - let domain = id. - toLowerCase(). - replace(/@/g, '-at-'). - replace(/\./g, '-dot-'). - replace(uuidRe, '$1'); - - let prefixURI = 'resource://' + domain + '/'; - let resourcesURI = ioService.newURI(rootURI + '/resources/'); - setResourceSubstitution(domain, resourcesURI); - - // Create path to URLs mapping supported by loader. - let paths = { - // Relative modules resolve to add-on package lib - './': prefixURI + name + '/lib/', - './tests/': prefixURI + name + '/tests/', - '': 'resource://gre/modules/commonjs/' - }; - - // Maps addon lib and tests ressource folders for each package - paths = Object.keys(options.metadata).reduce(function(result, name) { - result[name + '/'] = prefixURI + name + '/lib/' - result[name + '/tests/'] = prefixURI + name + '/tests/' - return result; - }, paths); - - // We need to map tests folder when we run sdk tests whose package name - // is stripped - if (name == 'addon-sdk') - paths['tests/'] = prefixURI + name + '/tests/'; - - let useBundledSDK = options['force-use-bundled-sdk']; - if (!useBundledSDK) { - try { - useBundledSDK = prefService.getBoolPref("extensions.addon-sdk.useBundledSDK"); - } - catch (e) { - // Pref doesn't exist, allow using Firefox shipped SDK - } - } - - // Starting with Firefox 21.0a1, we start using modules shipped into firefox - // Still allow using modules from the xpi if the manifest tell us to do so. - // And only try to look for sdk modules in xpi if the xpi actually ship them - if (options['is-sdk-bundled'] && - (vc.compare(appInfo.version, '21.0a1') < 0 || useBundledSDK)) { - // Maps sdk module folders to their resource folder - paths[''] = prefixURI + 'addon-sdk/lib/'; - // test.js is usually found in root commonjs or SDK_ROOT/lib/ folder, - // so that it isn't shipped in the xpi. Keep a copy of it in sdk/ folder - // until we no longer support SDK modules in XPI: - paths['test'] = prefixURI + 'addon-sdk/lib/sdk/test.js'; - } - - // Retrieve list of module folder overloads based on preferences in order to - // eventually used a local modules instead of files shipped into Firefox. - let branch = prefService.getBranch('extensions.modules.' + id + '.path'); - paths = branch.getChildList('', {}).reduce(function (result, name) { - // Allows overloading of any sub folder by replacing . by / in pref name - let path = name.substr(1).split('.').join('/'); - // Only accept overloading folder by ensuring always ending with `/` - if (path) path += '/'; - let fileURI = branch.getCharPref(name); - - // On mobile, file URI has to end with a `/` otherwise, setSubstitution - // takes the parent folder instead. - if (fileURI[fileURI.length-1] !== '/') - fileURI += '/'; - - // Maps the given file:// URI to a resource:// in order to avoid various - // failure that happens with file:// URI and be close to production env - let resourcesURI = ioService.newURI(fileURI); - let resName = 'extensions.modules.' + domain + '.commonjs.path' + name; - setResourceSubstitution(resName, resourcesURI); - - result[path] = 'resource://' + resName + '/'; - return result; - }, paths); - - // Make version 2 of the manifest - let manifest = options.manifest; - - // Import `cuddlefish.js` module using a Sandbox and bootstrap loader. - let cuddlefishPath = 'loader/cuddlefish.js'; - let cuddlefishURI = 'resource://gre/modules/commonjs/sdk/' + cuddlefishPath; - if (paths['sdk/']) { // sdk folder has been overloaded - // (from pref, or cuddlefish is still in the xpi) - cuddlefishURI = paths['sdk/'] + cuddlefishPath; - } - else if (paths['']) { // root modules folder has been overloaded - cuddlefishURI = paths[''] + 'sdk/' + cuddlefishPath; - } - - cuddlefishSandbox = loadSandbox(cuddlefishURI); - let cuddlefish = cuddlefishSandbox.exports; - - // Normalize `options.mainPath` so that it looks like one that will come - // in a new version of linker. - let main = options.mainPath; - - unload = cuddlefish.unload; - loader = cuddlefish.Loader({ - paths: paths, - // modules manifest. - manifest: manifest, - - // Add-on ID used by different APIs as a unique identifier. - id: id, - // Add-on name. - name: name, - // Add-on version. - version: options.metadata[name].version, - // Add-on package descriptor. - metadata: options.metadata[name], - // Add-on load reason. - loadReason: reason, - - prefixURI: prefixURI, - // Add-on URI. - rootURI: rootURI, - // options used by system module. - // File to write 'OK' or 'FAIL' (exit code emulation). - resultFile: options.resultFile, - // Arguments passed as --static-args - staticArgs: options.staticArgs, - - // Option to prevent automatic kill of firefox during tests - noQuit: options.no_quit, - - // Add-on preferences branch name - preferencesBranch: options.preferencesBranch, - - // Arguments related to test runner. - modules: { - '@test/options': { - iterations: options.iterations, - filter: options.filter, - profileMemory: options.profileMemory, - stopOnError: options.stopOnError, - verbose: options.verbose, - parseable: options.parseable, - checkMemory: options.check_memory, - } - } - }); - - let module = cuddlefish.Module('sdk/loader/cuddlefish', cuddlefishURI); - let require = cuddlefish.Require(loader, module); - - // Init the 'sdk/webextension' module from the bootstrap addon parameter. - require("sdk/webextension").initFromBootstrapAddonParam(data); - - require('sdk/addon/runner').startup(reason, { - loader: loader, - main: main, - prefsURI: rootURI + 'defaults/preferences/prefs.js' - }); - } catch (error) { - dump('Bootstrap error: ' + - (error.message ? error.message : String(error)) + '\n' + - (error.stack || error.fileName + ': ' + error.lineNumber) + '\n'); - throw error; - } -}; - -function loadSandbox(uri) { - let proto = { - sandboxPrototype: { - loadSandbox: loadSandbox, - ChromeWorker: ChromeWorker - } - }; - let sandbox = Cu.Sandbox(systemPrincipal, proto); - // Create a fake commonjs environnement just to enable loading loader.js - // correctly - sandbox.exports = {}; - sandbox.module = { uri: uri, exports: sandbox.exports }; - sandbox.require = function (id) { - if (id !== "chrome") - throw new Error("Bootstrap sandbox `require` method isn't implemented."); - - return Object.freeze({ Cc: Cc, Ci: Ci, Cu: Cu, Cr: Cr, Cm: Cm, - CC: bind(CC, Components), components: Components, - ChromeWorker: ChromeWorker }); - }; - scriptLoader.loadSubScript(uri, sandbox, 'UTF-8'); - return sandbox; -} - -function unloadSandbox(sandbox) { - if (Cu.getClassName(sandbox, true) == "Sandbox") - Cu.nukeSandbox(sandbox); -} - -function setTimeout(callback, delay) { - let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); - timer.initWithCallback({ notify: callback }, delay, - Ci.nsITimer.TYPE_ONE_SHOT); - return timer; -} - -function shutdown(data, reasonCode) { - let reason = REASON[reasonCode]; - if (loader) { - unload(loader, reason); - unload = null; - - // Don't waste time cleaning up if the application is shutting down - if (reason != "shutdown") { - // Avoid leaking all modules when something goes wrong with one particular - // module. Do not clean it up immediatly in order to allow executing some - // actions on addon disabling. - // We need to keep a reference to the timer, otherwise it is collected - // and won't ever fire. - nukeTimer = setTimeout(nukeModules, 1000); - - // Bug 944951 - bootstrap.js must remove the added resource: URIs on unload - resourceDomains.forEach(domain => { - resourceHandler.setSubstitution(domain, null); - }) - } - } -}; - -function nukeModules() { - nukeTimer = null; - // module objects store `exports` which comes from sandboxes - // We should avoid keeping link to these object to avoid leaking sandboxes - for (let key in loader.modules) { - delete loader.modules[key]; - } - // Direct links to sandboxes should be removed too - for (let key in loader.sandboxes) { - let sandbox = loader.sandboxes[key]; - delete loader.sandboxes[key]; - // Bug 775067: From FF17 we can kill all CCW from a given sandbox - unloadSandbox(sandbox); - } - unloadSandbox(loader.sharedGlobalSandbox); - loader = null; - - // both `toolkit/loader` and `system/xul-app` are loaded as JSM's via - // `cuddlefish.js`, and needs to be unloaded to avoid memory leaks, when - // the addon is unload. - - unloadSandbox(cuddlefishSandbox.loaderSandbox); - - // Bug 764840: We need to unload cuddlefish otherwise it will stay alive - // and keep a reference to this compartment. - unloadSandbox(cuddlefishSandbox); - cuddlefishSandbox = null; -} diff --git a/addon-sdk/source/app-extension/install.rdf b/addon-sdk/source/app-extension/install.rdf deleted file mode 100644 --- a/addon-sdk/source/app-extension/install.rdf +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - xulapp@toolness.com - 1.0 - 2 - true - false - - - - - {ec8030f7-c20a-464f-9b0e-13a3a9e97384} - 26.0 - 30.0 - - - - - Test App - Harness for tests. - Mozilla Corporation - - - - - - diff --git a/addon-sdk/source/bin/activate b/addon-sdk/source/bin/activate deleted file mode 100644 --- a/addon-sdk/source/bin/activate +++ /dev/null @@ -1,84 +0,0 @@ -# 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/. - -# This file must be used with "source bin/activate" *from bash* -# you cannot run it directly - -deactivate () { - if [ -n "$_OLD_VIRTUAL_PATH" ] ; then - PATH="$_OLD_VIRTUAL_PATH" - export PATH - unset _OLD_VIRTUAL_PATH - fi - - # This should detect bash and zsh, which have a hash command that must - # be called to get it to forget past commands. Without forgetting - # past commands the $PATH changes we made may not be respected - if [ -n "$BASH" -o -n "$ZSH_VERSION" ] ; then - hash -r - fi - - if [ -n "$_OLD_VIRTUAL_PS1" ] ; then - PS1="$_OLD_VIRTUAL_PS1" - export PS1 - unset _OLD_VIRTUAL_PS1 - fi - - PYTHONPATH="$_OLD_PYTHONPATH" - export PYTHONPATH - unset _OLD_PYTHONPATH - - unset CUDDLEFISH_ROOT - - unset VIRTUAL_ENV - if [ ! "$1" = "nondestructive" ] ; then - # Self destruct! - unset deactivate - fi -} - -# unset irrelavent variables -deactivate nondestructive - -_OLD_PYTHONPATH="$PYTHONPATH" -_OLD_VIRTUAL_PATH="$PATH" - -VIRTUAL_ENV="`pwd`" - -if [ "x$OSTYPE" = "xmsys" ] ; then - CUDDLEFISH_ROOT="`pwd -W | sed s,/,\\\\\\\\,g`" - PATH="`pwd`/bin:$PATH" - # msys will convert any env vars with PATH in it to use msys - # form and will unconvert before launching - PYTHONPATH="`pwd -W`/python-lib;$PYTHONPATH" -else - CUDDLEFISH_ROOT="$VIRTUAL_ENV" - PYTHONPATH="$VIRTUAL_ENV/python-lib:$PYTHONPATH" - PATH="$VIRTUAL_ENV/bin:$PATH" -fi - -VIRTUAL_ENV="`pwd`" - -export CUDDLEFISH_ROOT -export PYTHONPATH -export PATH - -_OLD_VIRTUAL_PS1="$PS1" -if [ "`basename \"$VIRTUAL_ENV\"`" = "__" ] ; then - # special case for Aspen magic directories - # see http://www.zetadev.com/software/aspen/ - PS1="[`basename \`dirname \"$VIRTUAL_ENV\"\``] $PS1" -else - PS1="(`basename \"$VIRTUAL_ENV\"`)$PS1" -fi -export PS1 - -# This should detect bash and zsh, which have a hash command that must -# be called to get it to forget past commands. Without forgetting -# past commands the $PATH changes we made may not be respected -if [ -n "$BASH" -o -n "$ZSH_VERSION" ] ; then - hash -r -fi - -python -c "from jetpack_sdk_env import welcome; welcome()" diff --git a/addon-sdk/source/bin/activate.bat b/addon-sdk/source/bin/activate.bat deleted file mode 100644 --- a/addon-sdk/source/bin/activate.bat +++ /dev/null @@ -1,134 +0,0 @@ -@echo off -rem This Source Code Form is subject to the terms of the Mozilla Public -rem License, v. 2.0. If a copy of the MPL was not distributed with this -rem file, You can obtain one at http://mozilla.org/MPL/2.0/. - -set VIRTUAL_ENV=%~dp0 -set VIRTUAL_ENV=%VIRTUAL_ENV:~0,-5% -set CUDDLEFISH_ROOT=%VIRTUAL_ENV% - -SET PYTHONKEY=SOFTWARE\Python\PythonCore - -rem look for 32-bit windows and python, or 64-bit windows and python - -SET PYTHONVERSION=2.7 -call:CheckPython PYTHONINSTALL %PYTHONKEY%\%PYTHONVERSION%\InstallPath -if "%PYTHONINSTALL%" NEQ "" goto FoundPython - -SET PYTHONVERSION=2.6 -call:CheckPython PYTHONINSTALL %PYTHONKEY%\%PYTHONVERSION%\InstallPath -if "%PYTHONINSTALL%" NEQ "" goto FoundPython - -SET PYTHONVERSION=2.5 -call:CheckPython PYTHONINSTALL %PYTHONKEY%\%PYTHONVERSION%\InstallPath -if "%PYTHONINSTALL%" NEQ "" goto FoundPython - -if not defined ProgramFiles(x86) goto win32 - -rem look for 32-bit python on 64-bit windows - -SET PYTHONKEY=SOFTWARE\Wow6432Node\Python\PythonCore - -SET PYTHONVERSION=2.7 -call:CheckPython PYTHONINSTALL %PYTHONKEY%\%PYTHONVERSION%\InstallPath -if "%PYTHONINSTALL%" NEQ "" goto FoundPython - -SET PYTHONVERSION=2.6 -call:CheckPython PYTHONINSTALL %PYTHONKEY%\%PYTHONVERSION%\InstallPath -if "%PYTHONINSTALL%" NEQ "" goto FoundPython - -SET PYTHONVERSION=2.5 -call:CheckPython PYTHONINSTALL %PYTHONKEY%\%PYTHONVERSION%\InstallPath -if "%PYTHONINSTALL%" NEQ "" goto FoundPython - -:win32 - -SET PYTHONVERSION= -set PYTHONKEY= -echo Warning: Failed to find Python installation directory -goto :EOF - -:FoundPython - -if defined _OLD_PYTHONPATH ( - set PYTHONPATH=%_OLD_PYTHONPATH% -) -if not defined PYTHONPATH ( - set PYTHONPATH=; -) -set _OLD_PYTHONPATH=%PYTHONPATH% -set PYTHONPATH=%VIRTUAL_ENV%\python-lib;%PYTHONPATH% - -if not defined PROMPT ( - set PROMPT=$P$G -) - -if defined _OLD_VIRTUAL_PROMPT ( - set PROMPT=%_OLD_VIRTUAL_PROMPT% -) - -set _OLD_VIRTUAL_PROMPT=%PROMPT% -set PROMPT=(%VIRTUAL_ENV%) %PROMPT% - -if defined _OLD_VIRTUAL_PATH goto OLDPATH -goto SKIPPATH -:OLDPATH -PATH %_OLD_VIRTUAL_PATH% - -:SKIPPATH -set _OLD_VIRTUAL_PATH=%PATH% -PATH %VIRTUAL_ENV%\bin;%PYTHONINSTALL%;%PATH% -set PYTHONKEY= -set PYTHONINSTALL= -set PYTHONVERSION= -set key= -set reg= -set _tokens= -python -c "from jetpack_sdk_env import welcome; welcome()" -GOTO :EOF - -:CheckPython -::CheckPython(retVal, key) -::Reads the registry at %2% and checks if a Python exists there. -::Checks both HKLM and HKCU, then checks the executable actually exists. -SET key=%2% -SET "%~1=" -SET reg=reg -if defined ProgramFiles(x86) ( - rem 32-bit cmd on 64-bit windows - if exist %WINDIR%\sysnative\reg.exe SET reg=%WINDIR%\sysnative\reg.exe -) -rem On Vista+, the last line of output is: -rem (default) REG_SZ the_value -rem (but note the word "default" will be localized. -rem On XP, the last line of output is: -rem \tREG_SZ\tthe_value -rem (not sure if "NO NAME" is localized or not!) -rem SO: we use ")>" as the tokens to split on, then nuke -rem the REG_SZ and any tabs or spaces. -FOR /F "usebackq tokens=2 delims=)>" %%A IN (`%reg% QUERY HKLM\%key% /ve 2^>NUL`) DO SET "%~1=%%A" -rem Remove the REG_SZ -set PYTHONINSTALL=%PYTHONINSTALL:REG_SZ=% -rem Remove tabs (note the literal \t in the next line -set PYTHONINSTALL=%PYTHONINSTALL: =% -rem Remove spaces. -set PYTHONINSTALL=%PYTHONINSTALL: =% -if exist %PYTHONINSTALL%\python.exe goto :EOF -rem It may be a 32bit Python directory built from source, in which case the -rem executable is in the PCBuild directory. -if exist %PYTHONINSTALL%\PCBuild\python.exe (set "PYTHONINSTALL=%PYTHONINSTALL%\PCBuild" & goto :EOF) -rem Or maybe a 64bit build directory. -if exist %PYTHONINSTALL%\PCBuild\amd64\python.exe (set "PYTHONINSTALL=%PYTHONINSTALL%\PCBuild\amd64" & goto :EOF) - -rem And try HKCU -FOR /F "usebackq tokens=2 delims=)>" %%A IN (`%reg% QUERY HKCU\%key% /ve 2^>NUL`) DO SET "%~1=%%A" -set PYTHONINSTALL=%PYTHONINSTALL:REG_SZ=% -set PYTHONINSTALL=%PYTHONINSTALL: =% -set PYTHONINSTALL=%PYTHONINSTALL: =% -if exist %PYTHONINSTALL%\python.exe goto :EOF -if exist %PYTHONINSTALL%\PCBuild\python.exe (set "PYTHONINSTALL=%PYTHONINSTALL%\PCBuild" & goto :EOF) -if exist %PYTHONINSTALL%\PCBuild\amd64\python.exe (set "PYTHONINSTALL=%PYTHONINSTALL%\PCBuild\amd64" & goto :EOF) -rem can't find it here, so arrange to try the next key -set PYTHONINSTALL= - -GOTO :EOF diff --git a/addon-sdk/source/bin/activate.fish b/addon-sdk/source/bin/activate.fish deleted file mode 100644 --- a/addon-sdk/source/bin/activate.fish +++ /dev/null @@ -1,66 +0,0 @@ -# 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/. - -# This file must be used with "source bin/activate.fish" *from fish* -# you cannot run it directly - -# Much of this code is based off of the activate.fish file for the -# virtualenv project. http://ur1.ca/ehmd6 - -function deactivate -d "Exit addon-sdk and return to normal shell environment" - if test -n "$_OLD_VIRTUAL_PATH" - set -gx PATH $_OLD_VIRTUAL_PATH - set -e _OLD_VIRTUAL_PATH - end - - if test -n "$_OLD_PYTHONPATH" - set -gx PYTHONPATH $_OLD_PYTHONPATH - set -e _OLD_PYTHONPATH - end - - if test -n "$_OLD_FISH_PROMPT_OVERRIDE" - functions -e fish_prompt - set -e _OLD_FISH_PROMPT_OVERRIDE - . ( begin - printf "function fish_prompt\n\t#" - functions _old_fish_prompt - end | psub ) - - functions -e _old_fish_prompt - end - - set -e CUDDLEFISH_ROOT - set -e VIRTUAL_ENV - - if test "$argv[1]" != "nondestructive" - functions -e deactivate - end -end - -# unset irrelavent variables -deactivate nondestructive - -set -gx _OLD_PYTHONPATH $PYTHONPATH -set -gx _OLD_VIRTUAL_PATH $PATH -set -gx _OLD_FISH_PROMPT_OVERRIDE "true" - -set VIRTUAL_ENV (pwd) - -set -gx CUDDLEFISH_ROOT $VIRTUAL_ENV -set -gx PYTHONPATH "$VIRTUAL_ENV/python-lib" $PYTHONPATH -set -gx PATH "$VIRTUAL_ENV/bin" $PATH - -# save the current fish_prompt function as the function _old_fish_prompt -. ( begin - printf "function _old_fish_prompt\n\t#" - functions fish_prompt - end | psub ) - -# with the original prompt function renamed, we can override with our own. -function fish_prompt - printf "(%s)%s%s" (basename "$VIRTUAL_ENV") (set_color normal) (_old_fish_prompt) - return -end - -python -c "from jetpack_sdk_env import welcome; welcome()" diff --git a/addon-sdk/source/bin/activate.ps1 b/addon-sdk/source/bin/activate.ps1 deleted file mode 100644 --- a/addon-sdk/source/bin/activate.ps1 +++ /dev/null @@ -1,99 +0,0 @@ -# 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/. - -$Env:VIRTUAL_ENV = (gl); -$Env:CUDDLEFISH_ROOT = $Env:VIRTUAL_ENV; - -# http://stackoverflow.com/questions/5648931/powershell-test-if-registry-value-exists/5652674#5652674 -Function Test-RegistryValue { - param( - [Alias("PSPath")] - [Parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] - [String]$Path - , - [Parameter(Position = 1, Mandatory = $true)] - [String]$Name - , - [Switch]$PassThru - ) - - process { - if (Test-Path $Path) { - $Key = Get-Item -LiteralPath $Path - if ($Key.GetValue($Name, $null) -ne $null) { - if ($PassThru) { - Get-ItemProperty $Path $Name - } else { - $true - } - } else { - $false - } - } else { - $false - } - } -} - -$WINCURVERKEY = 'HKLM:SOFTWARE\Microsoft\Windows\CurrentVersion'; -$WIN64 = (Test-RegistryValue $WINCURVERKEY 'ProgramFilesDir (x86)'); - -if($WIN64) { - $PYTHONKEY='HKLM:SOFTWARE\Wow6432Node\Python\PythonCore'; -} -else { - $PYTHONKEY='HKLM:SOFTWARE\Python\PythonCore'; -} - -$Env:PYTHONVERSION = ''; -$Env:PYTHONINSTALL = ''; - -foreach ($version in @('2.6', '2.5', '2.4')) { - if (Test-RegistryValue "$PYTHONKEY\$version\InstallPath" '(default)') { - $Env:PYTHONVERSION = $version; - } -} - -if ($Env:PYTHONVERSION) { - $Env:PYTHONINSTALL = (Get-Item "$PYTHONKEY\$version\InstallPath)").'(default)'; -} - -if ($Env:PYTHONINSTALL) { - $Env:Path += ";$Env:PYTHONINSTALL"; -} - -if (Test-Path Env:_OLD_PYTHONPATH) { - $Env:PYTHONPATH = $Env:_OLD_PYTHONPATH; -} -else { - $Env:PYTHONPATH = ''; -} - -$Env:_OLD_PYTHONPATH=$Env:PYTHONPATH; -$Env:PYTHONPATH= "$Env:VIRTUAL_ENV\python-lib;$Env:PYTHONPATH"; - -if (Test-Path Function:_OLD_VIRTUAL_PROMPT) { - Set-Content Function:Prompt (Get-Content Function:_OLD_VIRTUAL_PROMPT); -} -else { - function global:_OLD_VIRTUAL_PROMPT {} -} - -Set-Content Function:_OLD_VIRTUAL_PROMPT (Get-Content Function:Prompt); - -function global:prompt { "($Env:VIRTUAL_ENV) $(_OLD_VIRTUAL_PROMPT)"; }; - -if (Test-Path Env:_OLD_VIRTUAL_PATH) { - $Env:PATH = $Env:_OLD_VIRTUAL_PATH; -} -else { - $Env:_OLD_VIRTUAL_PATH = $Env:PATH; -} - -$Env:Path="$Env:VIRTUAL_ENV\bin;$Env:Path" - -[System.Console]::WriteLine("Note: this PowerShell SDK activation script is experimental.") - -python -c "from jetpack_sdk_env import welcome; welcome()" - diff --git a/addon-sdk/source/bin/cfx b/addon-sdk/source/bin/cfx deleted file mode 100755 --- a/addon-sdk/source/bin/cfx +++ /dev/null @@ -1,33 +0,0 @@ -#! /usr/bin/env python -# 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/. - - -import os -import sys - -# set the cuddlefish "root directory" for this process if it's not already -# set in the environment -cuddlefish_root = os.path.dirname(os.path.dirname(os.path.realpath(sys.argv[0]))) - -if 'CUDDLEFISH_ROOT' not in os.environ: - os.environ['CUDDLEFISH_ROOT'] = cuddlefish_root - -# add our own python-lib path to the python module search path. -python_lib_dir = os.path.join(cuddlefish_root, "python-lib") -if python_lib_dir not in sys.path: - sys.path.insert(0, python_lib_dir) - -# now export to env so sub-processes get it too -if 'PYTHONPATH' not in os.environ: - os.environ['PYTHONPATH'] = python_lib_dir -elif python_lib_dir not in os.environ['PYTHONPATH'].split(os.pathsep): - paths = os.environ['PYTHONPATH'].split(os.pathsep) - paths.insert(0, python_lib_dir) - os.environ['PYTHONPATH'] = os.pathsep.join(paths) - -import cuddlefish - -if __name__ == '__main__': - cuddlefish.run() diff --git a/addon-sdk/source/bin/cfx.bat b/addon-sdk/source/bin/cfx.bat deleted file mode 100644 --- a/addon-sdk/source/bin/cfx.bat +++ /dev/null @@ -1,6 +0,0 @@ -@echo off -rem This Source Code Form is subject to the terms of the Mozilla Public -rem License, v. 2.0. If a copy of the MPL was not distributed with this -rem file, You can obtain one at http://mozilla.org/MPL/2.0/. - -python "%VIRTUAL_ENV%\bin\cfx" %* diff --git a/addon-sdk/source/bin/deactivate.bat b/addon-sdk/source/bin/deactivate.bat deleted file mode 100644 --- a/addon-sdk/source/bin/deactivate.bat +++ /dev/null @@ -1,23 +0,0 @@ -@echo off -rem This Source Code Form is subject to the terms of the Mozilla Public -rem License, v. 2.0. If a copy of the MPL was not distributed with this -rem file, You can obtain one at http://mozilla.org/MPL/2.0/. - -if defined _OLD_VIRTUAL_PROMPT ( - set "PROMPT=%_OLD_VIRTUAL_PROMPT%" -) -set _OLD_VIRTUAL_PROMPT= - -if defined _OLD_VIRTUAL_PATH ( - set "PATH=%_OLD_VIRTUAL_PATH%" -) -set _OLD_VIRTUAL_PATH= - -if defined _OLD_PYTHONPATH ( - set "PYTHONPATH=%_OLD_PYTHONPATH%" -) -set _OLD_PYTHONPATH= - -set CUDDLEFISH_ROOT= - -:END diff --git a/addon-sdk/source/bin/fx-download.sh b/addon-sdk/source/bin/fx-download.sh deleted file mode 100644 --- a/addon-sdk/source/bin/fx-download.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/sh - -if [ "$JPM_FX_DEBUG" = "1" ]; then - fx-download --branch nightly -c prerelease --host ftp.mozilla.org ../firefox --debug -else - fx-download --branch nightly -c prerelease --host ftp.mozilla.org ../firefox -fi diff --git a/addon-sdk/source/bin/integration-scripts/buildbot-run-cfx-helper b/addon-sdk/source/bin/integration-scripts/buildbot-run-cfx-helper deleted file mode 100755 --- a/addon-sdk/source/bin/integration-scripts/buildbot-run-cfx-helper +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash -# 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/. - - -source ./bin/activate -if [ type -P xvfb-run ] -then - xvfb-run cfx $* -else - cfx $* -fi -deactivate diff --git a/addon-sdk/source/bin/integration-scripts/integration-check b/addon-sdk/source/bin/integration-scripts/integration-check deleted file mode 100644 --- a/addon-sdk/source/bin/integration-scripts/integration-check +++ /dev/null @@ -1,364 +0,0 @@ -#!/usr/bin/env python -# 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/. - -import os -import signal -import threading -import urllib2, urllib -import zipfile -import tarfile -import subprocess -import optparse -import sys, re -#import win32api - - -class SDK: - def __init__(self): - try: - # Take the current working directory - self.default_path = os.getcwd() - if sys.platform == "win32": - self.mswindows = True - else: - self.mswindows = False - # Take the default home path of the user. - home = os.path.expanduser('~') - - # The following are the parameters that can be used to pass a dynamic URL, a specific path or a binry. The binary is not used yet. It will be used in version 2.0 - # If a dynamic path is to be mentioned, it should start with a '/'. For eg. "/Desktop" - parser = optparse.OptionParser() - parser.add_option('-u', '--url', dest = 'url', default = 'https://ftp.mozilla.org/pub/mozilla.org/labs/jetpack/addon-sdk-latest.zip') - parser.add_option('-p', '--path', dest = 'path', default = self.default_path) - parser.add_option('-b', '--binary', dest = 'binary')#, default='/Applications/Firefox.app') - (options, args) = parser.parse_args() - - # Get the URL from the parameter - self.link = options.url - # Set the base path for the user. If the user supplies the path, use the home variable as well. Else, take the default path of this script as the installation directory. - if options.path!=self.default_path: - if self.mswindows: - self.base_path = home + str(options.path).strip() + '\\' - else: - self.base_path = home + str(options.path).strip() + '/' - else: - if self.mswindows: - self.base_path = str(options.path).strip() + '\\' - else: - self.base_path = str(options.path).strip() + '/' - assert ' ' not in self.base_path, "You cannot have a space in your home path. Please remove the space before you continue." - print('Your Base path is =' + self.base_path) - - # This assignment is not used in this program. It will be used in version 2 of this script. - self.bin = options.binary - # if app or bin is empty, dont pass anything - - # Search for the .zip file or tarball file in the URL. - i = self.link.rfind('/') - - self.fname = self.link[i+1:] - z = re.search('zip',self.fname,re.I) - g = re.search('gz',self.fname,re.I) - if z: - print 'zip file present in the URL.' - self.zip = True - self.gz = False - elif g: - print 'gz file present in the URL' - self.gz = True - self.zip = False - else: - print 'zip/gz file not present. Check the URL.' - return - print("File name is =" + self.fname) - - # Join the base path and the zip/tar file name to crate a complete Local file path. - self.fpath = self.base_path + self.fname - print('Your local file path will be=' + self.fpath) - except AssertionError, e: - print e.args[0] - sys.exit(1) - - # Download function - to download the SDK from the URL to the local machine. - def download(self,url,fpath,fname): - try: - # Start the download - print("Downloading...Please be patient!") - urllib.urlretrieve(url,filename = fname) - print('Download was successful.') - except ValueError: # Handles broken URL errors. - print 'The URL is ether broken or the file does not exist. Please enter the correct URL.' - raise - except urllib2.URLError: # Handles URL errors - print '\nURL not correct. Check again!' - raise - - # Function to extract the downloaded zipfile. - def extract(self, zipfilepath, extfile): - try: - # Timeout is set to 30 seconds. - timeout = 30 - # Change the directory to the location of the zip file. - try: - os.chdir(zipfilepath) - except OSError: - # Will reach here if zip file doesnt exist - print 'O/S Error:' + zipfilepath + 'does not exist' - raise - - # Get the folder name of Jetpack to get the exact version number. - if self.zip: - try: - f = zipfile.ZipFile(extfile, "r") - except IOError as (errno, strerror): # Handles file errors - print "I/O error - Cannot perform extract operation: {1}".format(errno, strerror) - raise - list = f.namelist()[0] - temp_name = list.split('/') - print('Folder Name= ' +temp_name[0]) - self.folder_name = temp_name[0] - elif self.gz: - try: - f = tarfile.open(extfile,'r') - except IOError as (errno, strerror): # Handles file errors - print "I/O error - Cannot perform extract operation: {1}".format(errno, strerror) - raise - list = f.getnames()[0] - temp_name = list.split('/') - print('Folder Name= ' +temp_name[0]) - self.folder_name = temp_name[0] - - print ('Starting to Extract...') - - # Timeout code. The subprocess.popen exeutes the command and the thread waits for a timeout. If the process does not finish within the mentioned- - # timeout, the process is killed. - kill_check = threading.Event() - - if self.zip: - # Call the command to unzip the file. - if self.mswindows: - zipfile.ZipFile.extractall(f) - else: - p = subprocess.Popen('unzip '+extfile, stdout=subprocess.PIPE, shell=True) - pid = p.pid - elif self.gz: - # Call the command to untar the file. - if self.mswindows: - tarfile.TarFile.extractall(f) - else: - p = subprocess.Popen('tar -xf '+extfile, stdout=subprocess.PIPE, shell=True) - pid = p.pid - - #No need to handle for windows because windows automatically replaces old files with new files. It does not ask the user(as it does in Mac/Unix) - if self.mswindows==False: - watch = threading.Timer(timeout, kill_process, args=(pid, kill_check, self.mswindows )) - watch.start() - (stdout, stderr) = p.communicate() - watch.cancel() # if it's still waiting to run - success = not kill_check.isSet() - - # Abort process if process fails. - if not success: - raise RuntimeError - kill_check.clear() - print('Extraction Successful.') - except RuntimeError: - print "Ending the program" - sys.exit(1) - except: - print "Error during file extraction: ", sys.exc_info()[0] - raise - - # Function to run the cfx testall comands and to make sure the SDK is not broken. - def run_testall(self, home_path, folder_name): - try: - timeout = 500 - - self.new_dir = home_path + folder_name - try: - os.chdir(self.new_dir) - except OSError: - # Will reach here if the jetpack 0.X directory doesnt exist - print 'O/S Error: Jetpack directory does not exist at ' + self.new_dir - raise - print '\nStarting tests...' - # Timeout code. The subprocess.popen exeutes the command and the thread waits for a timeout. If the process does not finish within the mentioned- - # timeout, the process is killed. - kill_check = threading.Event() - - # Set the path for the logs. They will be in the parent directory of the Jetpack SDK. - log_path = home_path + 'tests.log' - - # Subprocess call to set up the jetpack environment and to start the tests. Also sends the output to a log file. - if self.bin != None: - if self.mswindows: - p = subprocess.Popen("bin\\activate && cfx testall -a firefox -b \"" + self.bin + "\"" , stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) - proc_handle = p._handle - (stdout,stderr) = p.communicate() - else: - p = subprocess.Popen('. bin/activate; cfx testall -a firefox -b ' + self.bin , stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) - pid = p.pid - (stdout,stderr) = p.communicate() - elif self.bin == None: - if self.mswindows: - p=subprocess.Popen('bin\\activate && cfx testall -a firefox > '+log_path, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) - proc_handle = p._handle - (stdout,stderr) = p.communicate() - else: - p = subprocess.Popen('. bin/activate; cfx testall -a firefox > '+log_path, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) - pid = p.pid - (stdout,stderr) = p.communicate() - - #Write the output to log file - f=open(log_path,"w") - f.write(stdout+stderr) - f.close() - - #Watchdog for timeout process - if self.mswindows: - watch = threading.Timer(timeout, kill_process, args=(proc_handle, kill_check, self.mswindows)) - else: - watch = threading.Timer(timeout, kill_process, args=(pid, kill_check, self.mswindows)) - watch.start() - watch.cancel() # if it's still waiting to run - success = not kill_check.isSet() - if not success: - raise RuntimeError - kill_check.clear() - - if p.returncode!=0: - print('\nAll tests were not successful. Check the test-logs in the jetpack directory.') - result_sdk(home_path) - #sys.exit(1) - raise RuntimeError - else: - ret_code=result_sdk(home_path) - if ret_code==0: - print('\nAll tests were successful. Yay \o/ . Running a sample package test now...') - else: - print ('\nThere were errors during the tests.Take a look at logs') - raise RuntimeError - except RuntimeError: - print "Ending the program" - sys.exit(1) - except: - print "Error during the testall command execution:", sys.exc_info()[0] - raise - - def package(self, example_dir): - try: - timeout = 30 - - print '\nNow Running packaging tests...' - - kill_check = threading.Event() - - # Set the path for the example logs. They will be in the parent directory of the Jetpack SDK. - exlog_path = example_dir + 'test-example.log' - # Subprocess call to test the sample example for packaging. - if self.bin!=None: - if self.mswindows: - p = subprocess.Popen('bin\\activate && cfx run --pkgdir examples\\reading-data --static-args="{\\"quitWhenDone\\":true}" -b \"" + self.bin + "\"' , stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) - proc_handle = p._handle - (stdout, stderr) = p.communicate() - else: - p = subprocess.Popen('. bin/activate; cfx run --pkgdir examples/reading-data --static-args=\'{\"quitWhenDone\":true}\' -b ' + self.bin , stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) - pid = p.pid - (stdout, stderr) = p.communicate() - elif self.bin==None: - if self.mswindows: - p = subprocess.Popen('bin\\activate && cfx run --pkgdir examples\\reading-data --static-args="{\\"quitWhenDone\\":true}"', stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) - proc_handle = p._handle - (stdout, stderr) = p.communicate() - else: - p = subprocess.Popen('. bin/activate; cfx run --pkgdir examples/reading-data --static-args=\'{\"quitWhenDone\":true}\' ', stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) - pid = p.pid - (stdout, stderr) = p.communicate() - - #Write the output to log file - f=open(exlog_path,"w") - f.write(stdout+stderr) - f.close() - - #Watch dog for timeout process - if self.mswindows: - watch = threading.Timer(timeout, kill_process, args=(proc_handle, kill_check, self.mswindows)) - else: - watch = threading.Timer(timeout, kill_process, args=(pid, kill_check, self.mswindows)) - watch.start() - watch.cancel() # if it's still waiting to run - success = not kill_check.isSet() - if not success: - raise RuntimeError - kill_check.clear() - - if p.returncode != 0: - print('\nSample tests were not executed correctly. Check the test-example log in jetpack diretory.') - result_example(example_dir) - raise RuntimeError - else: - ret_code=result_example(example_dir) - if ret_code==0: - print('\nAll tests pass. The SDK is working! Yay \o/') - else: - print ('\nTests passed with warning.Take a look at logs') - sys.exit(1) - - except RuntimeError: - print "Ending program" - sys.exit(1) - except: - print "Error during running sample tests:", sys.exc_info()[0] - raise - -def result_sdk(sdk_dir): - log_path = sdk_dir + 'tests.log' - print 'Results are logged at:' + log_path - try: - f = open(log_path,'r') - # Handles file errors - except IOError : - print 'I/O error - Cannot open test log at ' + log_path - raise - - for line in reversed(open(log_path).readlines()): - if line.strip()=='FAIL': - print ('\nOverall result - FAIL. Look at the test log at '+log_path) - return 1 - return 0 - - -def result_example(sdk_dir): - exlog_path = sdk_dir + 'test-example.log' - print 'Sample test results are logged at:' + exlog_path - try: - f = open(exlog_path,'r') - # Handles file errors - except IOError : - print 'I/O error - Cannot open sample test log at ' + exlog_path - raise - - #Read the file in reverse and check for the keyword 'FAIL'. - for line in reversed(open(exlog_path).readlines()): - if line.strip()=='FAIL': - print ('\nOverall result for Sample tests - FAIL. Look at the test log at '+exlog_path) - return 1 - return 0 - -def kill_process(process, kill_check, mswindows): - print '\nProcess Timedout. Killing the process. Please Rerun this script.' - if mswindows: - win32api.TerminateProcess(process, -1) - else: - os.kill(process, signal.SIGKILL) - kill_check.set()# tell the main routine to kill. Used SIGKILL to hard kill the process. - return - -if __name__ == "__main__": - obj = SDK() - obj.download(obj.link,obj.fpath,obj.fname) - obj.extract(obj.base_path,obj.fname) - obj.run_testall(obj.base_path,obj.folder_name) - obj.package(obj.base_path) diff --git a/addon-sdk/source/bin/jpm-test.js b/addon-sdk/source/bin/jpm-test.js deleted file mode 100644 --- a/addon-sdk/source/bin/jpm-test.js +++ /dev/null @@ -1,34 +0,0 @@ -/* 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/. */ -"use strict"; - -var Promise = require("promise"); -var Mocha = require("mocha"); -var mocha = new Mocha({ - ui: "bdd", - reporter: "spec", - timeout: 900000 -}); - -var isDebug = require("./node-scripts/utils").isDebug; - -exports.run = function(type) { - return new Promise(function(resolve) { - type = type || ""; - [ - (!isDebug && /^(firefox-bin)?$/.test(type)) && require.resolve("../bin/node-scripts/test.firefox-bin"), - (!isDebug && /^(docs)?$/.test(type)) && require.resolve("../bin/node-scripts/test.docs"), - (!isDebug && /^(ini)?$/.test(type)) && require.resolve("../bin/node-scripts/test.ini"), - (/^(examples)?$/.test(type)) && require.resolve("../bin/node-scripts/test.examples"), - (!isDebug && /^(addons)?$/.test(type)) && require.resolve("../bin/node-scripts/test.addons"), - (!isDebug && /^(modules)?$/.test(type)) && require.resolve("../bin/node-scripts/test.modules"), - ].forEach(function(filepath) { - filepath && mocha.addFile(filepath); - }) - - mocha.run(function(failures) { - resolve(failures); - }); - }); -} diff --git a/addon-sdk/source/bin/node-scripts/apply-patch.js b/addon-sdk/source/bin/node-scripts/apply-patch.js deleted file mode 100644 --- a/addon-sdk/source/bin/node-scripts/apply-patch.js +++ /dev/null @@ -1,64 +0,0 @@ -/* 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/. */ -"use strict"; - -var path = require("path"); -var cp = require("child_process"); -var fs = require("fs"); -var Promise = require("promise"); -var patcher = require("patch-editor"); -var readParam = require("./utils").readParam; - -var isKeeper = /\/addon-sdk\/source/; - -function apply(options) { - return clean(options).then(function() { - return new Promise(function(resolve) { - var patch = path.resolve(readParam("patch")); - var proc = cp.spawn("git", ["apply", patch]); - proc.stdout.pipe(process.stdout); - proc.stderr.pipe(process.stderr); - proc.on("close", resolve); - }); - }); -} -exports.apply = apply; - -function clean(options) { - return new Promise(function(resolve) { - var patch = path.resolve(readParam("patch")); - if (!patch) { - throw new Error("no --patch was provided."); - } - console.log("Cleaning patch " + patch); - - patcher.getChunks({ patch: patch }).then(function(chunks) { - var keepers = []; - - for (var i = chunks.length - 1; i >= 0; i--) { - var chunk = chunks[i]; - var files = chunk.getFilesChanged(); - - // check if the file changed is related to the addon-sdk/source directory - var keepIt = files.map(function(file) { - return (isKeeper.test(file)); - }).reduce(function(prev, curr) { - return prev || curr; - }, false); - - if (keepIt) { - keepers.push(chunk); - } - } - - var contents = "\n" + keepers.join("\n") + "\n"; - contents = contents.replace(/\/addon-sdk\/source/g, ""); - - fs.writeFileSync(patch, contents, { encoding: "utf8" }); - - console.log("Done cleaning patch."); - }).then(resolve).catch(console.error); - }); -} -exports.clean = clean; diff --git a/addon-sdk/source/bin/node-scripts/test.addons.js b/addon-sdk/source/bin/node-scripts/test.addons.js deleted file mode 100644 --- a/addon-sdk/source/bin/node-scripts/test.addons.js +++ /dev/null @@ -1,57 +0,0 @@ -/* 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/. */ -"use strict"; - -var utils = require("./utils"); -var path = require("path"); -var fs = require("fs"); -var jpm = utils.run; -var readParam = utils.readParam; -var isDebug = utils.isDebug; - -var addonsPath = path.join(__dirname, "..", "..", "test", "addons"); - -var binary = process.env.JPM_FIREFOX_BINARY || "nightly"; -var filterPattern = readParam("filter"); - -describe("jpm test sdk addons", function () { - fs.readdirSync(addonsPath) - .filter(fileFilter.bind(null, addonsPath)) - .forEach(function (file) { - it(file, function (done) { - var addonPath = path.join(addonsPath, file); - process.chdir(addonPath); - - var options = { cwd: addonPath, env: { JPM_FIREFOX_BINARY: binary }}; - if (process.env.DISPLAY) { - options.env.DISPLAY = process.env.DISPLAY; - } - if (/^e10s/.test(file)) { - options.e10s = true; - } - - jpm("run", options).then(done).catch(done); - }); - }); -}); - -function fileFilter(root, file) { - var matcher = filterPattern && new RegExp(filterPattern); - if (/^(l10n-properties|simple-prefs|page-mod-debugger)/.test(file)) { - return false; - } - - // filter additional add-ons when using debug builds - if (isDebug) { - if (/^(chrome|e10s)/.test(file)) { - return false; - } - } - - if (matcher && !matcher.test(file)) { - return false; - } - var stat = fs.statSync(path.join(root, file)) - return (stat && stat.isDirectory()); -} diff --git a/addon-sdk/source/bin/node-scripts/test.docs.js b/addon-sdk/source/bin/node-scripts/test.docs.js deleted file mode 100644 --- a/addon-sdk/source/bin/node-scripts/test.docs.js +++ /dev/null @@ -1,145 +0,0 @@ -/* 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/. */ -"use strict"; - -var createHash = require('crypto').createHash; -var fs = require("fs"); -var fsExtra = require("fs-extra") -var path = require("path"); -var Promise = require("promise"); -var chai = require("chai"); -var expect = chai.expect; -var teacher = require("teacher"); - -var rootURI = path.join(__dirname, "..", ".."); - -// get a list of words that fail spell check but are still acceptable -var NEW_WORDS = fs.readFileSync(path.join(__dirname, "words.txt")).toString().trim().split("\n"); - -var CACHE_PATH = path.join(__dirname, "..", "..", "cache", "spellchecks.json"); - -var CACHE = {}; - -try { - CACHE = JSON.parse(fs.readFileSync(CACHE_PATH).toString()); -} -catch (e) {} - -function md5(str) { - return createHash("md5").update(str).digest("utf8"); -} - -function addCacheHash(hash) { - CACHE[hash] = true; - fsExtra.ensureFileSync(CACHE_PATH); - fsExtra.writeJSONSync(CACHE_PATH, CACHE); -} - -describe("Spell Checking", function () { - it("Spellcheck CONTRIBUTING.md", function (done) { - var readme = path.join(rootURI, "CONTRIBUTING.md"); - - fs.readFile(readme, function (err, data) { - if (err) { - throw err; - } - var text = data.toString(); - var hash = md5(text); - - // skip this test if we know we have done the - // exact same test with positive results before - if (CACHE[hash]) { - expect(CACHE[hash]).to.be.equal(true); - return done(); - } - - teacher.check(text, function(err, data) { - expect(err).to.be.equal(null); - - var results = data || []; - results = results.filter(function(result) { - if (NEW_WORDS.indexOf(result.string.toLowerCase()) != -1) { - return false; - } - - // ignore anything that starts with a dash - if (result.string[0] == "-") { - return false; - } - - if (!(new RegExp(result.string)).test(text)) { - return false; - } - - return true; - }) - - if (results.length > 0) { - console.log(results); - } - else { - addCacheHash(hash); - } - - expect(results.length).to.be.equal(0); - - setTimeout(done, 500); - }); - }); - }); - - it("Spellcheck README.md", function (done) { - var readme = path.join(rootURI, "README.md"); - - fs.readFile(readme, function (err, data) { - if (err) { - throw err; - } - var text = data.toString(); - var hash = md5(text); - - // skip this test if we know we have done the - // exact same test with positive results before - if (CACHE[hash]) { - expect(CACHE[hash]).to.be.equal(true); - return done(); - } - - teacher.check(text, function(err, data) { - expect(err).to.be.equal(null); - - var results = data || []; - results = results.filter(function(result) { - if (NEW_WORDS.indexOf(result.string.toLowerCase()) != -1) { - return false; - } - - // ignore anything that starts with a dash - if (result.string[0] == "-") { - return false; - } - - // ignore anything that we don't find in the original text, - // for some reason "bootstrap.js" becomes "bootstrapjs". - if (!(new RegExp(result.string)).test(text)) { - return false; - } - - return true; - }) - - if (results.length > 0) { - console.log(results); - } - else { - addCacheHash(hash); - } - - expect(results.length).to.be.equal(0); - - done(); - }); - }); - }); -}); diff --git a/addon-sdk/source/bin/node-scripts/test.examples.js b/addon-sdk/source/bin/node-scripts/test.examples.js deleted file mode 100644 --- a/addon-sdk/source/bin/node-scripts/test.examples.js +++ /dev/null @@ -1,45 +0,0 @@ -/* 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/. */ -"use strict"; - -var utils = require("./utils"); -var path = require("path"); -var fs = require("fs"); -var jpm = utils.run; -var readParam = utils.readParam; - -var examplesPath = path.join(__dirname, "..", "..", "examples"); - -var binary = process.env.JPM_FIREFOX_BINARY || "nightly"; -var filterPattern = readParam("filter"); - -describe("jpm test sdk examples", function () { - fs.readdirSync(examplesPath) - .filter(fileFilter.bind(null, examplesPath)) - .forEach(function (file) { - it(file, function (done) { - var addonPath = path.join(examplesPath, file); - process.chdir(addonPath); - - var options = { cwd: addonPath, env: { JPM_FIREFOX_BINARY: binary }}; - if (process.env.DISPLAY) { - options.env.DISPLAY = process.env.DISPLAY; - } - - jpm("test", options).then(done); - }); - }); -}); - -function fileFilter(root, file) { - var matcher = filterPattern && new RegExp(filterPattern); - if (/^(reading-data)/.test(file)) { - return false; - } - if (matcher && !matcher.test(file)) { - return false; - } - var stat = fs.statSync(path.join(root, file)) - return (stat && stat.isDirectory()); -} diff --git a/addon-sdk/source/bin/node-scripts/test.firefox-bin.js b/addon-sdk/source/bin/node-scripts/test.firefox-bin.js deleted file mode 100644 --- a/addon-sdk/source/bin/node-scripts/test.firefox-bin.js +++ /dev/null @@ -1,37 +0,0 @@ -/* 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/. */ -"use strict"; - -var fs = require("fs"); -var Promise = require("promise"); -var chai = require("chai"); -var expect = chai.expect; -var normalizeBinary = require("fx-runner/lib/utils").normalizeBinary; - -//var firefox_binary = process.env["JPM_FIREFOX_BINARY"] || normalizeBinary("nightly"); - -describe("Checking Firefox binary", function () { - - it("using matching fx-runner version with jpm", function () { - var sdkPackageJSON = require("../../package.json"); - var jpmPackageINI = require("jpm/package.json"); - expect(sdkPackageJSON.devDependencies["fx-runner"]).to.be.equal(jpmPackageINI.dependencies["fx-runner"]); - }); - - it("exists", function (done) { - var useEnvVar = new Promise(function(resolve) { - resolve(process.env["JPM_FIREFOX_BINARY"]); - }); - - var firefox_binary = process.env["JPM_FIREFOX_BINARY"] ? useEnvVar : normalizeBinary("nightly"); - firefox_binary.then(function(path) { - expect(path).to.be.ok; - fs.exists(path, function (exists) { - expect(exists).to.be.ok; - done(); - }); - }) - }); - -}); diff --git a/addon-sdk/source/bin/node-scripts/test.ini.js b/addon-sdk/source/bin/node-scripts/test.ini.js deleted file mode 100644 --- a/addon-sdk/source/bin/node-scripts/test.ini.js +++ /dev/null @@ -1,68 +0,0 @@ -/* 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/. */ -"use strict"; - -var fs = require("fs"); -var path = require("path"); -var Promise = require("promise"); -var chai = require("chai"); -var expect = chai.expect; -var ini = require("./update-ini"); - -var addonINI = path.resolve("./test/addons/jetpack-addon.ini"); -var packageINI = path.resolve("./test/jetpack-package.ini"); - -describe("Checking ini files", function () { - - it("Check test/addons/jetpack-addon.ini", function (done) { - - fs.readFile(addonINI, function (err, data) { - if (err) { - throw err; - } - // filter comments - var text = data.toString().split("\n").filter(function(line) { - return !/^\s*#/.test(line); - }).join("\n"); - var expected = ""; - - ini.makeAddonIniContent() - .then(function(contents) { - expected = contents; - - setTimeout(function end() { - expect(text.trim()).to.be.equal(expected.trim()); - done(); - }); - }); - }); - - }); - - it("Check test/jetpack-package.ini", function (done) { - - fs.readFile(packageINI, function (err, data) { - if (err) { - throw err; - } - // filter comments - var text = data.toString().split("\n").filter(function(line) { - return !/^\s*#/.test(line); - }).join("\n"); - var expected = ""; - - ini.makePackageIniContent() - .then(function(contents) { - expected = contents; - - setTimeout(function end() { - expect(text.trim()).to.be.equal(expected.trim()); - done(); - }); - }); - }); - - }); - -}); diff --git a/addon-sdk/source/bin/node-scripts/test.modules.js b/addon-sdk/source/bin/node-scripts/test.modules.js deleted file mode 100644 --- a/addon-sdk/source/bin/node-scripts/test.modules.js +++ /dev/null @@ -1,28 +0,0 @@ -/* 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/. */ -"use strict"; - -var utils = require("./utils"); -var readParam = utils.readParam; -var path = require("path"); -var fs = require("fs"); -var jpm = utils.run; -var sdk = path.join(__dirname, "..", ".."); -var binary = process.env.JPM_FIREFOX_BINARY || "nightly"; - -var filterPattern = readParam("filter"); - -describe("jpm test sdk modules", function () { - it("SDK Modules", function (done) { - process.chdir(sdk); - - var options = { cwd: sdk, env: { JPM_FIREFOX_BINARY: binary } }; - if (process.env.DISPLAY) { - options.env.DISPLAY = process.env.DISPLAY; - } - options.filter = filterPattern; - - jpm("test", options, process).then(done); - }); -}); diff --git a/addon-sdk/source/bin/node-scripts/update-ini.js b/addon-sdk/source/bin/node-scripts/update-ini.js deleted file mode 100644 --- a/addon-sdk/source/bin/node-scripts/update-ini.js +++ /dev/null @@ -1,141 +0,0 @@ -/* 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/. */ -"use strict"; - -var path = require("path"); -var cp = require("child_process"); -var fs = require("fs"); -var Promise = require("promise"); -var parser = require("ini-parser"); - -var addonINI = path.resolve("./test/addons/jetpack-addon.ini"); -var addonsDir = path.resolve("./test/addons/"); -var packageINI = path.resolve("./test/jetpack-package.ini"); -var packageDir = path.resolve("./test/"); -var packageIgnorables = [ "addons", "preferences" ]; -var packageSupportFiles = [ - "fixtures.js", - "test-context-menu.html", - "util.js" -] - -function updateAddonINI() { - return new Promise(function(resolve) { - console.log("Start updating " + addonINI); - - makeAddonIniContent(). - then(function(contents) { - fs.writeFileSync(addonINI, contents, { encoding: "utf8" }); - console.log("Done updating " + addonINI); - resolve(); - }); - }) -} -exports.updateAddonINI = updateAddonINI; - -function makeAddonIniContent() { - return new Promise(function(resolve) { - var data = parser.parse(fs.readFileSync(addonINI, { encoding: "utf8" }).toString()); - var result = {}; - - fs.readdir(addonsDir, function(err, files) { - // get a list of folders - var folders = files.filter(function(file) { - return fs.statSync(path.resolve(addonsDir, file)).isDirectory(); - }).sort(); - - // copy any related data from the existing ini - folders.forEach(function(folder) { - var oldData = data[folder + ".xpi"]; - result[folder] = oldData ? oldData : {}; - }); - - // build a new ini file - var contents = []; - Object.keys(result).sort().forEach(function(key) { - contents.push("[" + key + ".xpi]"); - Object.keys(result[key]).forEach(function(dataKey) { - contents.push(dataKey + " = " + result[key][dataKey]); - }); - }); - contents = contents.join("\n") + "\n"; - - return resolve(contents); - }); - }); -} -exports.makeAddonIniContent = makeAddonIniContent; - -function makePackageIniContent() { - return new Promise(function(resolve) { - var data = parser.parse(fs.readFileSync(packageINI, { encoding: "utf8" }).toString()); - var result = {}; - - fs.readdir(packageDir, function(err, files) { - // get a list of folders - var folders = files.filter(function(file) { - var ignore = (packageIgnorables.indexOf(file) >= 0); - var isDir = fs.statSync(path.resolve(packageDir, file)).isDirectory(); - return (isDir && !ignore); - }).sort(); - - // get a list of "test-"" files - var files = files.filter(function(file) { - var ignore = !/^test\-.*\.js$/i.test(file); - var isDir = fs.statSync(path.resolve(packageDir, file)).isDirectory(); - return (!isDir && !ignore); - }).sort(); - - // get a list of the support files - var support_files = packageSupportFiles.map(function(file) { - return " " + file; - }); - folders.forEach(function(folder) { - support_files.push(" " + folder + "/**"); - }); - support_files = support_files.sort(); - - // copy any related data from the existing ini - files.forEach(function(file) { - var oldData = data[file]; - result[file] = oldData ? oldData : {}; - }); - - // build a new ini file - var contents = [ - "[DEFAULT]", - "support-files =" - ]; - support_files.forEach(function(support_file) { - contents.push(support_file); - }); - contents.push(""); - - Object.keys(result).sort().forEach(function(key) { - contents.push("[" + key + "]"); - Object.keys(result[key]).forEach(function(dataKey) { - contents.push(dataKey + " = " + result[key][dataKey]); - }); - }); - contents = contents.join("\n") + "\n"; - - return resolve(contents); - }); - }); -} -exports.makePackageIniContent = makePackageIniContent; - -function updatePackageINI() { - return new Promise(function(resolve) { - console.log("Start updating " + packageINI); - - makeAddonIniContent(). - then(function(contents) { - fs.writeFileSync(packageINI, contents, { encoding: "utf8" }); - console.log("Done updating " + packageINI); - resolve(); - }); - }) -} -exports.updatePackageINI = updatePackageINI; diff --git a/addon-sdk/source/bin/node-scripts/utils.js b/addon-sdk/source/bin/node-scripts/utils.js deleted file mode 100644 --- a/addon-sdk/source/bin/node-scripts/utils.js +++ /dev/null @@ -1,104 +0,0 @@ -/* 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/. */ -"use strict"; - -var _ = require("lodash"); -var path = require("path"); -var child_process = require("child_process"); -var jpm = require.resolve("../../node_modules/jpm/bin/jpm"); -var Promise = require("promise"); -var chai = require("chai"); -var expect = chai.expect; -var assert = chai.assert; -var DEFAULT_PROCESS = process; - -var sdk = path.join(__dirname, "..", ".."); -var prefsPath = path.join(sdk, "test", "preferences", "test-preferences.js"); -var e10sPrefsPath = path.join(sdk, "test", "preferences", "test-e10s-preferences.js"); - -var OUTPUT_FILTERS = [ - /[^\n\r]+WARNING\: NS_ENSURE_SUCCESS\(rv, rv\) failed[^\n]+\n\r?/ -]; - -var isDebug = (process.env["JPM_FX_DEBUG"] == "1"); -exports.isDebug = isDebug; - -function spawn (cmd, options) { - options = options || {}; - var env = _.extend({}, options.env, process.env); - - if (isDebug) { - env["MOZ_QUIET"] = 1; - } - - var e10s = options.e10s || false; - - return child_process.spawn("node", [ - jpm, cmd, "-v", "--tbpl", - "--prefs", e10s ? e10sPrefsPath : prefsPath, - "-o", sdk, - "-f", options.filter || "" - ], { - cwd: options.cwd || tmpOutputDir, - env: env - }); -} -exports.spawn = spawn; - -function run (cmd, options, p) { - return new Promise(function(resolve) { - var output = []; - - var proc = spawn(cmd, options); - proc.stderr.pipe(process.stderr); - proc.stdout.on("data", function (data) { - for (var i = OUTPUT_FILTERS.length - 1; i >= 0; i--) { - if (OUTPUT_FILTERS[i].test(data)) { - return null; - } - } - output.push(data); - return null; - }); - - if (p) { - proc.stdout.pipe(p.stdout); - } - else if (!isDebug) { - proc.stdout.pipe(DEFAULT_PROCESS.stdout); - } - else { - proc.stdout.on("data", function (data) { - data = (data || "") + ""; - if (/TEST-/.test(data)) { - DEFAULT_PROCESS.stdout.write(data.replace(/[\s\n]+$/, "") + "\n"); - } - }); - } - - proc.on("close", function(code) { - var out = output.join(""); - var buildDisplayed = /Build \d+/.test(out); - var noTests = /No tests were run/.test(out); - var hasSuccess = /All tests passed!/.test(out); - var hasFailure = /There were test failures\.\.\./.test(out); - if (noTests || hasFailure || !hasSuccess || code != 0) { - DEFAULT_PROCESS.stdout.write(out); - } - expect(code).to.equal(hasFailure ? 1 : 0); - expect(buildDisplayed).to.equal(true); - expect(hasFailure).to.equal(false); - expect(hasSuccess).to.equal(true); - expect(noTests).to.equal(false); - resolve(); - }); - }); -} -exports.run = run; - -function readParam(name) { - var index = process.argv.indexOf("--" + name) - return index >= 0 && process.argv[index + 1] -} -exports.readParam = readParam; diff --git a/addon-sdk/source/bin/node-scripts/words.txt b/addon-sdk/source/bin/node-scripts/words.txt deleted file mode 100644 --- a/addon-sdk/source/bin/node-scripts/words.txt +++ /dev/null @@ -1,11 +0,0 @@ -addon-sdk -github -stackoverflow -bugzilla -irc -jsantell -mossop -gozala -zer0 -autonome -0c0w3 diff --git a/addon-sdk/source/examples/actor-repl/README.md b/addon-sdk/source/examples/actor-repl/README.md deleted file mode 100644 --- a/addon-sdk/source/examples/actor-repl/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Actor REPL - -Simple REPL for a Firefox debugging protocol. diff --git a/addon-sdk/source/examples/actor-repl/data/codemirror-compressed.js b/addon-sdk/source/examples/actor-repl/data/codemirror-compressed.js deleted file mode 100644 --- a/addon-sdk/source/examples/actor-repl/data/codemirror-compressed.js +++ /dev/null @@ -1,5 +0,0 @@ -window.CodeMirror=function(){"use strict";function z(a,c){if(!(this instanceof z))return new z(a,c);this.options=c=c||{};for(var d in fd)!c.hasOwnProperty(d)&&fd.hasOwnProperty(d)&&(c[d]=fd[d]);M(c);var e="string"==typeof c.value?0:c.value.first,f=this.display=A(a,e);f.wrapper.CodeMirror=this,J(this),c.autofocus&&!r&&Qb(this),this.state={keyMaps:[],overlays:[],modeGen:0,overwrite:!1,focused:!1,suppressEdits:!1,pasteIncoming:!1,cutIncoming:!1,draggingText:!1,highlight:new jf},H(this),c.lineWrapping&&(this.display.wrapper.className+=" CodeMirror-wrap");var g=c.value;"string"==typeof g&&(g=new te(c.value,c.mode)),Ib(this,xe)(this,g),b&&setTimeout(tf(Pb,this,!0),20),Tb(this);var h;try{h=document.activeElement==f.input}catch(i){}h||c.autofocus&&!r?setTimeout(tf(rc,this),20):sc(this),Ib(this,function(){for(var a in ed)ed.propertyIsEnumerable(a)&&ed[a](this,c[a],hd);for(var b=0;bb.maxLineLength&&(b.maxLineLength=d,b.maxLine=a)})}function M(a){var b=pf(a.gutters,"CodeMirror-linenumbers");-1==b&&a.lineNumbers?a.gutters=a.gutters.concat(["CodeMirror-linenumbers"]):b>-1&&!a.lineNumbers&&(a.gutters=a.gutters.slice(0),a.gutters.splice(b,1))}function N(a){var b=a.display,c=a.doc.height,d=c+jb(b);b.sizer.style.minHeight=b.heightForcer.style.top=d+"px",b.gutters.style.height=Math.max(d,b.scroller.clientHeight-gf)+"px";var e=Math.max(d,b.scroller.scrollHeight),f=b.scroller.scrollWidth>b.scroller.clientWidth+1,g=e>b.scroller.clientHeight+1;g?(b.scrollbarV.style.display="block",b.scrollbarV.style.bottom=f?Hf(b.measure)+"px":"0",b.scrollbarV.firstChild.style.height=Math.max(0,e-b.scroller.clientHeight+b.scrollbarV.clientHeight)+"px"):(b.scrollbarV.style.display="",b.scrollbarV.firstChild.style.height="0"),f?(b.scrollbarH.style.display="block",b.scrollbarH.style.right=g?Hf(b.measure)+"px":"0",b.scrollbarH.firstChild.style.width=b.scroller.scrollWidth-b.scroller.clientWidth+b.scrollbarH.clientWidth+"px"):(b.scrollbarH.style.display="",b.scrollbarH.firstChild.style.width="0"),f&&g?(b.scrollbarFiller.style.display="block",b.scrollbarFiller.style.height=b.scrollbarFiller.style.width=Hf(b.measure)+"px"):b.scrollbarFiller.style.display="",f&&a.options.coverGutterNextToScrollbar&&a.options.fixedGutter?(b.gutterFiller.style.display="block",b.gutterFiller.style.height=Hf(b.measure)+"px",b.gutterFiller.style.width=b.gutters.offsetWidth+"px"):b.gutterFiller.style.display="",n&&0===Hf(b.measure)&&(b.scrollbarV.style.minWidth=b.scrollbarH.style.minHeight=o?"18px":"12px",b.scrollbarV.style.pointerEvents=b.scrollbarH.style.pointerEvents="none")}function O(a,b,c){var d=a.scroller.scrollTop,e=a.wrapper.clientHeight;"number"==typeof c?d=c:c&&(d=c.top,e=c.bottom-c.top),d=Math.floor(d-ib(a));var f=Math.ceil(d+e);return{from:De(b,d),to:De(b,f)}}function P(a){var b=a.display;if(b.alignWidgets||b.gutters.firstChild&&a.options.fixedGutter){for(var c=S(b)-b.scroller.scrollLeft+a.doc.scrollLeft,d=b.gutters.offsetWidth,e=c+"px",f=b.lineDiv.firstChild;f;f=f.nextSibling)if(f.alignable)for(var g=0,h=f.alignable;g=a.display.showingFrom&&h.to<=a.display.showingTo)break}return g&&(bf(a,"update",a),(a.display.showingFrom!=e||a.display.showingTo!=f)&&bf(a,"viewportChange",a,a.display.showingFrom,a.display.showingTo)),g}function U(a,b,c,d){var e=a.display,f=a.doc;if(!e.wrapper.offsetWidth)return e.showingFrom=e.showingTo=f.first,e.viewOffset=0,void 0;if(!(!d&&0==b.length&&c.from>e.showingFrom&&c.tol&&e.showingTo-l<20&&(l=Math.min(j,e.showingTo)),y)for(k=Ce(Rd(f,ye(f,k)));j>l&&Sd(f,ye(f,l));)++l;var m=[{from:Math.max(e.showingFrom,f.first),to:Math.min(e.showingTo,j)}];if(m=m[0].from>=m[0].to?[]:X(m,b),y)for(var i=0;in.from)){m.splice(i--,1);break}n.to=p}for(var q=0,i=0;il&&(n.to=l),n.from>=n.to?m.splice(i--,1):q+=n.to-n.from}if(!d&&q==l-k&&k==e.showingFrom&&l==e.showingTo)return W(a),void 0;m.sort(function(a,b){return a.from-b.from});try{var r=document.activeElement}catch(s){}.7*(l-k)>q&&(e.lineDiv.style.display="none"),Z(a,k,l,m,h),e.lineDiv.style.display="",r&&document.activeElement!=r&&r.offsetHeight&&r.focus();var t=k!=e.showingFrom||l!=e.showingTo||e.lastSizeC!=e.wrapper.clientHeight;return t&&(e.lastSizeC=e.wrapper.clientHeight,eb(a,400)),e.showingFrom=k,e.showingTo=l,e.gutters.style.height="",V(a),W(a),!0}}function V(a){for(var f,b=a.display,d=b.lineDiv.offsetTop,e=b.lineDiv.firstChild;e;e=e.nextSibling)if(e.lineObj){if(c){var g=e.offsetTop+e.offsetHeight;f=g-d,d=g}else{var h=Df(e);f=h.bottom-h.top}var i=e.lineObj.height-f;if(2>f&&(f=Db(b)),i>.001||-.001>i){Be(e.lineObj,f);var j=e.lineObj.widgets;if(j)for(var k=0;kc;++c){for(var e=b[c],f=[],g=e.diff||0,h=0,i=a.length;i>h;++h){var j=a[h];e.to<=j.from&&e.diff?f.push({from:j.from+g,to:j.to+g}):e.to<=j.from||e.from>=j.to?f.push(j):(e.from>j.from&&f.push({from:j.from,to:e.from}),e.ton){for(;k.lineObj!=b;)k=l(k);i&&n>=e&&k.lineNumber&&Cf(k.lineNumber,R(a.options,n)),k=k.nextSibling}else{if(b.widgets)for(var s,q=0,r=k;r&&20>q;++q,r=r.nextSibling)if(r.lineObj==b&&/div/i.test(r.nodeName)){s=r;break}var t=$(a,b,n,f,s);if(t!=s)j.insertBefore(t,k);else{for(;k!=s;)k=l(k);k=k.nextSibling}t.lineObj=b}++n});k;)k=l(k)}function $(a,b,d,e,f){var k,g=ie(a,b),h=g.pre,i=b.gutterMarkers,j=a.display,l=g.bgClass?g.bgClass+" "+(b.bgClass||""):b.bgClass;if(!(a.options.lineNumbers||i||l||b.wrapClass||b.widgets))return h;if(f){f.alignable=null;for(var q,m=!0,n=0,o=null,p=f.firstChild;p;p=q)if(q=p.nextSibling,/\bCodeMirror-linewidget\b/.test(p.className)){for(var r=0;rb&&(b=0),e.appendChild(zf("div",null,"CodeMirror-selected","position: absolute; left: "+a+"px; top: "+b+"px; width: "+(null==c?h-a:c)+"px; height: "+(d-b)+"px"))}function j(b,d,e){function m(c,d){return xb(a,Gc(b,c),"div",f,d)}var k,l,f=ye(c,b),j=f.text.length;return Of(Fe(f),d||0,null==e?j:e,function(a,b,c){var n,o,p,f=m(a,"left");if(a==b)n=f,o=p=f.left;else{if(n=m(b-1,"right"),"rtl"==c){var q=f;f=n,n=q}o=f.left,p=n.right}null==d&&0==a&&(o=g),n.top-f.top>3&&(i(o,f.top,null,f.bottom),o=g,f.bottoml.bottom||n.bottom==l.bottom&&n.right>l.right)&&(l=n),g+1>o&&(o=g),i(o,n.top,p-o,n.bottom)}),{start:k,end:l}}var b=a.display,c=a.doc,d=a.doc.sel,e=document.createDocumentFragment(),f=kb(a.display),g=f.left,h=b.lineSpace.offsetWidth-f.right;if(d.from.line==d.to.line)j(d.from.line,d.from.ch,d.to.ch);else{var k=ye(c,d.from.line),l=ye(c,d.to.line),m=Rd(c,k)==Rd(c,l),n=j(d.from.line,d.from.ch,m?k.text.length:null).end,o=j(d.to.line,m?0:null,d.to.ch).start;m&&(n.top0&&(b.blinker=setInterval(function(){b.cursor.style.visibility=b.otherCursor.style.visibility=(c=!c)?"":"hidden"},a.options.cursorBlinkRate))}}function eb(a,b){a.doc.mode.startState&&a.doc.frontier=a.display.showingTo)){var f,c=+new Date+a.options.workTime,d=nd(b.mode,hb(a,b.frontier)),e=[];b.iter(b.frontier,Math.min(b.first+b.size,a.display.showingTo+500),function(g){if(b.frontier>=a.display.showingFrom){var h=g.styles;g.styles=ce(a,g,d,!0);for(var i=!h||h.length!=g.styles.length,j=0;!i&&jc?(eb(a,a.options.workDelay),!0):void 0}),e.length&&Ib(a,function(){for(var a=0;ag;--h){if(h<=f.first)return f.first;var i=ye(f,h-1);if(i.stateAfter&&(!c||h<=f.frontier))return h;var j=kf(i.text,null,a.options.tabSize);(null==e||d>j)&&(e=h-1,d=j)}return e}function hb(a,b,c){var d=a.doc,e=a.display;if(!d.mode.startState)return!0;var f=gb(a,b,c),g=f>d.first&&ye(d,f-1).stateAfter;return g=g?nd(d.mode,g):od(d.mode),d.iter(f,b,function(c){ee(a,c.text,g);var h=f==b-1||0==f%5||f>=e.showingFrom&&ff&&0==h&&(f=1)}return e=h>c?"left":c>h?"right":e,"left"==e&&i.leftSide?i=i.leftSide:"right"==e&&i.rightSide&&(i=i.rightSide),{left:c>h?i.right:i.left,right:h>c?i.left:i.right,top:i.top,bottom:i.bottom}}function mb(a,b){for(var c=a.display.measureLineCache,d=0;ds&&(c=s),0>b&&(b=0);for(var d=q.length-2;d>=0;d-=2){var e=q[d],f=q[d+1];if(!(e>c||b>f)&&(b>=e&&f>=c||e>=b&&c>=f||Math.min(c,f)-Math.max(b,e)>=c-b>>1)){q[d]=Math.min(b,e),q[d+1]=Math.max(c,f);break}}return 0>d&&(d=q.length,q.push(b,c)),{left:a.left-p.left,right:a.right-p.left,top:d,bottom:null}}function u(a){a.bottom=q[a.top+1],a.top=q[a.top]}if(!a.options.lineWrapping&&e.text.length>=a.options.crudeMeasuringFrom)return qb(a,e);var f=a.display,g=sf(e.text.length),h=ie(a,e,g,!0).pre;if(b&&!c&&!a.options.lineWrapping&&h.childNodes.length>100){for(var i=document.createDocumentFragment(),j=10,k=h.childNodes.length,l=0,m=Math.ceil(k/j);m>l;++l){for(var n=zf("div",null,null,"display: inline-block"),o=0;j>o&&k;++o)n.appendChild(h.firstChild),--k;i.appendChild(n)}h.appendChild(i)}Bf(f.measure,h);var p=Df(f.lineDiv),q=[],r=sf(e.text.length),s=h.offsetHeight;d&&f.measure.first!=h&&Bf(f.measure,h);for(var v,l=0;l1&&(x=r[l]=t(y[0]),x.rightSide=t(y[y.length-1]))}x||(x=r[l]=t(Df(w))),v.measureRight&&(x.right=Df(v.measureRight).left-p.left),v.leftSide&&(x.leftSide=t(Df(v.leftSide)))}Af(a.display.measure);for(var v,l=0;l=a.options.crudeMeasuringFrom)return lb(a,b,b.text.length,f&&f.measure,"right").right;var g=ie(a,b,null,!0).pre,h=g.appendChild(Jf(a.display.measure));Bf(a.display.measure,g);var i=Df(h);return 0==i.right&&0==i.bottom&&(h=g.appendChild(zf("span","\xa0")),i=Df(h)),i.left-Df(a.display.lineDiv).left}function sb(a){a.display.measureLineCache.length=a.display.measureLineCachePos=0,a.display.cachedCharWidth=a.display.cachedTextHeight=a.display.cachedPaddingH=null,a.options.lineWrapping||(a.display.maxLineChanged=!0),a.display.lineNumChars=null}function tb(){return window.pageXOffset||(document.documentElement||document.body).scrollLeft}function ub(){return window.pageYOffset||(document.documentElement||document.body).scrollTop}function vb(a,b,c,d){if(b.widgets)for(var e=0;ec.from?f(a-1):f(a,d)}d=d||ye(a.doc,b.line),e||(e=ob(a,d));var h=Fe(d),i=b.ch;if(!h)return f(i);var j=Xf(h,i),k=g(i,j);return null!=Wf&&(k.other=g(i,Wf)),k}function zb(a,b,c,d){var e=new Gc(a,b);return e.xRel=d,c&&(e.outside=!0),e}function Ab(a,b,c){var d=a.doc;if(c+=a.display.viewOffset,0>c)return zb(d.first,0,!0,-1);var e=De(d,c),f=d.first+d.size-1;if(e>f)return zb(d.first+d.size-1,ye(d,f).text.length,!0,1);for(0>b&&(b=0);;){var g=ye(d,e),h=Bb(a,g,e,b,c),i=Pd(g),j=i&&i.find();if(!i||!(h.ch>j.from.ch||h.ch==j.from.ch&&h.xRel>0))return h;e=j.to.line}}function Bb(a,b,c,d,e){function j(d){var e=yb(a,Gc(c,d),"line",b,i);return g=!0,f>e.bottom?e.left-h:fq)return zb(c,n,r,1);for(;;){if(k?n==m||n==Zf(b,m,1):1>=n-m){for(var s=o>d||q-d>=d-o?m:n,t=d-(s==m?o:q);yf(b.text.charAt(s));)++s;var u=zb(c,s,s==m?p:r,0>t?-1:t?1:0);return u}var v=Math.ceil(l/2),w=m+v;if(k){w=m;for(var x=0;v>x;++x)w=Zf(b,w,1)}var y=j(w);y>d?(n=w,q=y,(r=g)&&(q+=1e3),l=v):(m=w,o=y,p=g,l-=v)}}function Db(a){if(null!=a.cachedTextHeight)return a.cachedTextHeight;if(null==Cb){Cb=zf("pre");for(var b=0;49>b;++b)Cb.appendChild(document.createTextNode("x")),Cb.appendChild(zf("br"));Cb.appendChild(document.createTextNode("x"))}Bf(a.measure,Cb);var c=Cb.offsetHeight/50;return c>3&&(a.cachedTextHeight=c),Af(a.measure),c||1}function Eb(a){if(null!=a.cachedCharWidth)return a.cachedCharWidth;var b=zf("span","x"),c=zf("pre",[b]);Bf(a.measure,c);var d=b.offsetWidth;return d>2&&(a.cachedCharWidth=d),d||10}function Gb(a){a.curOp={changes:[],forceUpdate:!1,updateInput:null,userSelChange:null,textChanged:null,selectionChanged:!1,cursorActivity:!1,updateMaxLine:!1,updateScrollPos:!1,id:++Fb},af++||(_e=[])}function Hb(a){var b=a.curOp,c=a.doc,d=a.display;if(a.curOp=null,b.updateMaxLine&&L(a),d.maxLineChanged&&!a.options.lineWrapping&&d.maxLine){var e=rb(a,d.maxLine);d.sizer.style.minWidth=Math.max(0,e+3)+"px",d.maxLineChanged=!1;var f=Math.max(0,d.sizer.offsetLeft+d.sizer.offsetWidth-d.scroller.clientWidth);fj&&c.charCodeAt(j)==h.charCodeAt(j);)++j;var l=f.from,m=f.to,n=h.slice(j);j-1){$c(a,f.head.line,"smart");break}}return h.length>1e3||h.indexOf("\n")>-1?b.value=a.display.prevInput="":a.display.prevInput=h,i&&Hb(a),a.state.pasteIncoming=a.state.cutIncoming=!1,!0}function Pb(a,b){var c,e,f=a.doc;if(Hc(f.sel.from,f.sel.to))b&&(a.display.prevInput=a.display.input.value="",g&&!d&&(a.display.inputHasSelection=null));else{a.display.prevInput="",c=Mf&&(f.sel.to.line-f.sel.from.line>100||(e=a.getSelection()).length>1e3);var h=c?"-":e||a.getSelection();a.display.input.value=h,a.state.focused&&of(a.display.input),g&&!d&&(a.display.inputHasSelection=h)}a.display.inaccurateSelection=c}function Qb(a){"nocursor"==a.options.readOnly||r&&document.activeElement==a.display.input||a.display.input.focus()}function Rb(a){a.state.focused||(Qb(a),rc(a))}function Sb(a){return a.options.readOnly||a.doc.cantEdit}function Tb(a){function e(){a.state.focused&&setTimeout(tf(Qb,a),0)}function i(){null==f&&(f=setTimeout(function(){f=null,c.cachedCharWidth=c.cachedTextHeight=c.cachedPaddingH=Gf=null,sb(a),Kb(a,tf(Lb,a))},100))}function j(){for(var a=c.wrapper.parentNode;a&&a!=document.body;a=a.parentNode);a?setTimeout(j,5e3):Ze(window,"resize",i)}function k(b){cf(a,b)||a.options.onDragEvent&&a.options.onDragEvent(a,Re(b))||Ve(b)}function l(b){c.inaccurateSelection&&(c.prevInput="",c.inaccurateSelection=!1,c.input.value=a.getSelection(),of(c.input)),"cut"==b.type&&(a.state.cutIncoming=!0)}var c=a.display;Ye(c.scroller,"mousedown",Ib(a,Yb)),b?Ye(c.scroller,"dblclick",Ib(a,function(b){if(!cf(a,b)){var c=Vb(a,b);if(c&&!_b(a,b)&&!Ub(a.display,b)){Se(b);var d=cd(ye(a.doc,c.line).text,c);Pc(a.doc,d.from,d.to)}}})):Ye(c.scroller,"dblclick",function(b){cf(a,b)||Se(b)}),Ye(c.lineSpace,"selectstart",function(a){Ub(c,a)||Se(a)}),w||Ye(c.scroller,"contextmenu",function(b){uc(a,b)}),Ye(c.scroller,"scroll",function(){c.scroller.clientHeight&&(dc(a,c.scroller.scrollTop),ec(a,c.scroller.scrollLeft,!0),$e(a,"scroll",a))}),Ye(c.scrollbarV,"scroll",function(){c.scroller.clientHeight&&dc(a,c.scrollbarV.scrollTop)}),Ye(c.scrollbarH,"scroll",function(){c.scroller.clientHeight&&ec(a,c.scrollbarH.scrollLeft)}),Ye(c.scroller,"mousewheel",function(b){hc(a,b)}),Ye(c.scroller,"DOMMouseScroll",function(b){hc(a,b)}),Ye(c.scrollbarH,"mousedown",e),Ye(c.scrollbarV,"mousedown",e),Ye(c.wrapper,"scroll",function(){c.wrapper.scrollTop=c.wrapper.scrollLeft=0});var f;Ye(window,"resize",i),setTimeout(j,5e3),Ye(c.input,"keyup",Ib(a,nc)),Ye(c.input,"input",function(){g&&!d&&a.display.inputHasSelection&&(a.display.inputHasSelection=null),Nb(a)}),Ye(c.input,"keydown",Ib(a,pc)),Ye(c.input,"keypress",Ib(a,qc)),Ye(c.input,"focus",tf(rc,a)),Ye(c.input,"blur",tf(sc,a)),a.options.dragDrop&&(Ye(c.scroller,"dragstart",function(b){cc(a,b)}),Ye(c.scroller,"dragenter",k),Ye(c.scroller,"dragover",k),Ye(c.scroller,"drop",Ib(a,bc))),Ye(c.scroller,"paste",function(b){Ub(c,b)||(Qb(a),Nb(a))}),Ye(c.input,"paste",function(){if(h&&!a.state.fakedLastChar&&!(new Date-a.state.lastMiddleDown<200)){var b=c.input.selectionStart,d=c.input.selectionEnd; -c.input.value+="$",c.input.selectionStart=b,c.input.selectionEnd=d,a.state.fakedLastChar=!0}a.state.pasteIncoming=!0,Nb(a)}),Ye(c.input,"cut",l),Ye(c.input,"copy",l),m&&Ye(c.sizer,"mouseup",function(){document.activeElement==c.input&&c.input.blur(),Qb(a)})}function Ub(a,b){for(var c=We(b);c!=a.wrapper;c=c.parentNode)if(!c||c.ignoreEvents||c.parentNode==a.sizer&&c!=a.mover)return!0}function Vb(a,b,c){var d=a.display;if(!c){var e=We(b);if(e==d.scrollbarH||e==d.scrollbarH.firstChild||e==d.scrollbarV||e==d.scrollbarV.firstChild||e==d.scrollbarFiller||e==d.gutterFiller)return null}var f,g,h=Df(d.lineSpace);try{f=b.clientX,g=b.clientY}catch(b){return null}return Ab(a,f-h.left,g-h.top)}function Yb(a){function t(a){if(!Hc(s,a)){if(s=a,"single"==m)return Pc(c.doc,Mc(i,k),a),void 0;if(q=Mc(i,q),r=Mc(i,r),"double"==m){var b=cd(ye(i,a.line).text,a);Ic(a,q)?Pc(c.doc,b.from,r):Pc(c.doc,q,b.to)}else"triple"==m&&(Ic(a,q)?Pc(c.doc,r,Mc(i,Gc(a.line,0))):Pc(c.doc,q,Mc(i,Gc(a.line+1,0))))}}function x(a){var b=++v,d=Vb(c,a,!0);if(d)if(Hc(d,o)){var g=a.clientYu.bottom?20:0;g&&setTimeout(Ib(c,function(){v==b&&(f.scroller.scrollTop+=g,x(a))}),50)}else{Rb(c),o=d,t(d);var e=O(f,i);(d.line>=e.to||d.linel-400&&Hc(Xb.pos,k))m="triple",Se(a),setTimeout(tf(Qb,c),20),dd(c,k.line);else if(Wb&&Wb.time>l-400&&Hc(Wb.pos,k)){m="double",Xb={time:l,pos:k},Se(a);var n=cd(ye(i,k.line).text,k);Pc(c.doc,n.from,n.to)}else Wb={time:l,pos:k};var o=k;if(c.options.dragDrop&&Ef&&!Sb(c)&&!Hc(j.from,j.to)&&!Ic(k,j.from)&&!Ic(j.to,k)&&"single"==m){var p=Ib(c,function(e){h&&(f.scroller.draggable=!1),c.state.draggingText=!1,Ze(document,"mouseup",p),Ze(f.scroller,"drop",p),Math.abs(a.clientX-e.clientX)+Math.abs(a.clientY-e.clientY)<10&&(Se(e),Pc(c.doc,k),Qb(c),b&&!d&&setTimeout(function(){document.body.focus(),Qb(c)},20))});return h&&(f.scroller.draggable=!0),c.state.draggingText=p,f.scroller.dragDrop&&f.scroller.dragDrop(),Ye(document,"mouseup",p),Ye(f.scroller,"drop",p),void 0}Se(a),"single"==m&&Pc(c.doc,Mc(i,k));var q=j.from,r=j.to,s=k,u=Df(f.wrapper),v=0,z=Ib(c,function(a){(g&&!e?a.buttons:Xe(a))?x(a):y(a)}),A=Ib(c,y);Ye(document,"mousemove",z),Ye(document,"mouseup",A)}}}function Zb(a,b,c,d,e){try{var f=b.clientX,g=b.clientY}catch(b){return!1}if(f>=Math.floor(Df(a.display.gutters).right))return!1;d&&Se(b);var h=a.display,i=Df(h.lineDiv);if(g>i.bottom||!ef(a,c))return Ue(b);g-=i.top-h.viewOffset;for(var j=0;j=f){var l=De(a.doc,g),m=a.options.gutters[j];return e(a,c,a,l,m,b),Ue(b)}}}function $b(a,b){return ef(a,"gutterContextMenu")?Zb(a,b,"gutterContextMenu",!1,$e):!1}function _b(a,b){return Zb(a,b,"gutterClick",!0,bf)}function bc(a){var b=this;if(!(cf(b,a)||Ub(b.display,a)||b.options.onDragEvent&&b.options.onDragEvent(b,Re(a)))){Se(a),g&&(ac=+new Date);var c=Vb(b,a,!0),d=a.dataTransfer.files;if(c&&!Sb(b))if(d&&d.length&&window.FileReader&&window.File)for(var e=d.length,f=Array(e),h=0,i=function(a,d){var g=new FileReader;g.onload=function(){f[d]=g.result,++h==e&&(c=Mc(b.doc,c),zc(b.doc,{from:c,to:c,text:Kf(f.join("\n")),origin:"paste"},"around"))},g.readAsText(a)},j=0;e>j;++j)i(d[j],j);else{if(b.state.draggingText&&!Ic(c,b.doc.sel.from)&&!Ic(b.doc.sel.to,c))return b.state.draggingText(a),setTimeout(tf(Qb,b),20),void 0;try{var f=a.dataTransfer.getData("Text");if(f){var k=b.doc.sel.from,l=b.doc.sel.to;Rc(b.doc,c,c),b.state.draggingText&&Fc(b.doc,"",k,l,"paste"),b.replaceSelection(f,null,"paste"),Qb(b)}}catch(a){}}}}function cc(a,b){if(g&&(!a.state.draggingText||+new Date-ac<100))return Ve(b),void 0;if(!cf(a,b)&&!Ub(a.display,b)){var c=a.getSelection();if(b.dataTransfer.setData("Text",c),b.dataTransfer.setDragImage&&!l){var d=zf("img",null,null,"position: fixed; left: 0; top: 0;");d.src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==",k&&(d.width=d.height=1,a.display.wrapper.appendChild(d),d._top=d.offsetTop),b.dataTransfer.setDragImage(d,0,0),k&&d.parentNode.removeChild(d)}}}function dc(b,c){Math.abs(b.doc.scrollTop-c)<2||(b.doc.scrollTop=c,a||T(b,[],c),b.display.scroller.scrollTop!=c&&(b.display.scroller.scrollTop=c),b.display.scrollbarV.scrollTop!=c&&(b.display.scrollbarV.scrollTop=c),a&&T(b,[]),eb(b,100))}function ec(a,b,c){(c?b==a.doc.scrollLeft:Math.abs(a.doc.scrollLeft-b)<2)||(b=Math.min(b,a.display.scroller.scrollWidth-a.display.scroller.clientWidth),a.doc.scrollLeft=b,P(a),a.display.scroller.scrollLeft!=b&&(a.display.scroller.scrollLeft=b),a.display.scrollbarH.scrollLeft!=b&&(a.display.scrollbarH.scrollLeft=b))}function hc(b,c){var d=c.wheelDeltaX,e=c.wheelDeltaY;null==d&&c.detail&&c.axis==c.HORIZONTAL_AXIS&&(d=c.detail),null==e&&c.detail&&c.axis==c.VERTICAL_AXIS?e=c.detail:null==e&&(e=c.wheelDelta);var f=b.display,g=f.scroller;if(d&&g.scrollWidth>g.clientWidth||e&&g.scrollHeight>g.clientHeight){if(e&&s&&h)for(var i=c.target;i!=g;i=i.parentNode)if(i.lineObj){b.display.currentWheelTarget=i;break}if(d&&!a&&!k&&null!=gc)return e&&dc(b,Math.max(0,Math.min(g.scrollTop+e*gc,g.scrollHeight-g.clientHeight))),ec(b,Math.max(0,Math.min(g.scrollLeft+d*gc,g.scrollWidth-g.clientWidth))),Se(c),f.wheelStartX=null,void 0;if(e&&null!=gc){var j=e*gc,l=b.doc.scrollTop,m=l+f.wrapper.clientHeight;0>j?l=Math.max(0,l+j-50):m=Math.min(b.doc.height,m+j+50),T(b,[],{top:l,bottom:m})}20>fc&&(null==f.wheelStartX?(f.wheelStartX=g.scrollLeft,f.wheelStartY=g.scrollTop,f.wheelDX=d,f.wheelDY=e,setTimeout(function(){if(null!=f.wheelStartX){var a=g.scrollLeft-f.wheelStartX,b=g.scrollTop-f.wheelStartY,c=b&&f.wheelDY&&b/f.wheelDY||a&&f.wheelDX&&a/f.wheelDX;f.wheelStartX=f.wheelStartY=null,c&&(gc=(gc*fc+c)/(fc+1),++fc)}},200)):(f.wheelDX+=d,f.wheelDY+=e))}}function ic(a,b,c){if("string"==typeof b&&(b=pd[b],!b))return!1;a.display.pollingFast&&Ob(a)&&(a.display.pollingFast=!1);var d=a.doc,e=d.sel.shift,f=!1;try{Sb(a)&&(a.state.suppressEdits=!0),c&&(d.sel.shift=!1),f=b(a)!=hf}finally{d.sel.shift=e,a.state.suppressEdits=!1}return f}function jc(a){var b=a.state.keyMaps.slice(0);return a.options.extraKeys&&b.push(a.options.extraKeys),b.push(a.options.keyMap),b}function lc(a,b){var c=rd(a.options.keyMap),e=c.auto;clearTimeout(kc),e&&!td(b)&&(kc=setTimeout(function(){rd(a.options.keyMap)==c&&(a.options.keyMap=e.call?e.call(null,a):e,G(a))},50));var f=ud(b,!0),g=!1;if(!f)return!1;var h=jc(a);return g=b.shiftKey?sd("Shift-"+f,h,function(b){return ic(a,b,!0)})||sd(f,h,function(b){return("string"==typeof b?/^go[A-Z]/.test(b):b.motion)?ic(a,b):void 0}):sd(f,h,function(b){return ic(a,b)}),g&&(Se(b),db(a),d&&(b.oldKeyCode=b.keyCode,b.keyCode=0),bf(a,"keyHandled",a,f,b)),g}function mc(a,b,c){var d=sd("'"+c+"'",jc(a),function(b){return ic(a,b,!0)});return d&&(Se(b),db(a),bf(a,"keyHandled",a,"'"+c+"'",b)),d}function nc(a){var b=this;cf(b,a)||b.options.onKeyEvent&&b.options.onKeyEvent(b,Re(a))||16==a.keyCode&&(b.doc.sel.shift=!1)}function pc(a){var c=this;if(Rb(c),!(cf(c,a)||c.options.onKeyEvent&&c.options.onKeyEvent(c,Re(a)))){b&&27==a.keyCode&&(a.returnValue=!1);var d=a.keyCode;c.doc.sel.shift=16==d||a.shiftKey;var e=lc(c,a);k&&(oc=e?d:null,!e&&88==d&&!Mf&&(s?a.metaKey:a.ctrlKey)&&c.replaceSelection(""))}}function qc(a){var b=this;if(!(cf(b,a)||b.options.onKeyEvent&&b.options.onKeyEvent(b,Re(a)))){var c=a.keyCode,e=a.charCode;if(k&&c==oc)return oc=null,Se(a),void 0;if(!(k&&(!a.which||a.which<10)||m)||!lc(b,a)){var f=String.fromCharCode(null==e?c:e);mc(b,a,f)||(g&&!d&&(b.display.inputHasSelection=null),Nb(b))}}}function rc(a){"nocursor"!=a.options.readOnly&&(a.state.focused||($e(a,"focus",a),a.state.focused=!0,-1==a.display.wrapper.className.search(/\bCodeMirror-focused\b/)&&(a.display.wrapper.className+=" CodeMirror-focused"),a.curOp||(Pb(a,!0),h&&setTimeout(tf(Pb,a,!0),0))),Mb(a),db(a))}function sc(a){a.state.focused&&($e(a,"blur",a),a.state.focused=!1,a.display.wrapper.className=a.display.wrapper.className.replace(" CodeMirror-focused","")),clearInterval(a.display.blinker),setTimeout(function(){a.state.focused||(a.doc.sel.shift=!1)},150)}function uc(a,b){function l(){if(null!=c.input.selectionStart){var a=c.input.value="\u200b"+(Hc(e.from,e.to)?"":c.input.value);c.prevInput="\u200b",c.input.selectionStart=1,c.input.selectionEnd=a.length}}function m(){if(c.inputDiv.style.position="relative",c.input.style.cssText=j,d&&(c.scrollbarV.scrollTop=c.scroller.scrollTop=h),Mb(a),null!=c.input.selectionStart){(!g||d)&&l(),clearTimeout(tc);var b=0,e=function(){"\u200b"==c.prevInput&&0==c.input.selectionStart?Ib(a,pd.selectAll)(a):b++<10?tc=setTimeout(e,500):Pb(a)};tc=setTimeout(e,200)}}if(!cf(a,b,"contextmenu")){var c=a.display,e=a.doc.sel;if(!Ub(c,b)&&!$b(a,b)){var f=Vb(a,b),h=c.scroller.scrollTop;if(f&&!k){var i=a.options.resetSelectionOnContextMenu;i&&(Hc(e.from,e.to)||Ic(f,e.from)||!Ic(f,e.to))&&Ib(a,Rc)(a.doc,f,f);var j=c.input.style.cssText;if(c.inputDiv.style.position="absolute",c.input.style.cssText="position: fixed; width: 30px; height: 30px; top: "+(b.clientY-5)+"px; left: "+(b.clientX-5)+"px; z-index: 1000; background: transparent; outline: none;"+"border-width: 0; outline: none; overflow: hidden; opacity: .05; -ms-opacity: .05; filter: alpha(opacity=5);",Qb(a),Pb(a,!0),Hc(e.from,e.to)&&(c.input.value=c.prevInput=" "),g&&!d&&l(),w){Ve(b);var n=function(){Ze(window,"mouseup",n),setTimeout(m,20)};Ye(window,"mouseup",n)}else setTimeout(m,50)}}}}function wc(a,b,c){if(!Ic(b.from,c))return Mc(a,c);var d=b.text.length-1-(b.to.line-b.from.line);if(c.line>b.to.line+d){var e=c.line-d,f=a.first+a.size-1;return e>f?Gc(f,ye(a,f).text.length):Nc(c,ye(a,e).text.length)}if(c.line==b.to.line+d)return Nc(c,nf(b.text).length+(1==b.text.length?b.from.ch:0)+ye(a,b.to.line).text.length-b.to.ch);var g=c.line-b.from.line;return Nc(c,b.text[g].length+(g?0:b.from.ch))}function xc(a,b,c){if(c&&"object"==typeof c)return{anchor:wc(a,b,c.anchor),head:wc(a,b,c.head)};if("start"==c)return{anchor:b.from,head:b.from};var d=vc(b);if("around"==c)return{anchor:b.from,head:d};if("end"==c)return{anchor:d,head:d};var e=function(a){if(Ic(a,b.from))return a;if(!Ic(b.to,a))return d;var c=a.line+b.text.length-(b.to.line-b.from.line)-1,e=a.ch;return a.line==b.to.line&&(e+=d.ch-b.to.ch),Gc(c,e)};return{anchor:e(a.sel.anchor),head:e(a.sel.head)}}function yc(a,b,c){var d={canceled:!1,from:b.from,to:b.to,text:b.text,origin:b.origin,cancel:function(){this.canceled=!0}};return c&&(d.update=function(b,c,d,e){b&&(this.from=Mc(a,b)),c&&(this.to=Mc(a,c)),d&&(this.text=d),void 0!==e&&(this.origin=e)}),$e(a,"beforeChange",a,d),a.cm&&$e(a.cm,"beforeChange",a.cm,d),d.canceled?null:{from:d.from,to:d.to,text:d.text,origin:d.origin}}function zc(a,b,c,d){if(a.cm){if(!a.cm.curOp)return Ib(a.cm,zc)(a,b,c,d);if(a.cm.state.suppressEdits)return}if(!(ef(a,"beforeChange")||a.cm&&ef(a.cm,"beforeChange"))||(b=yc(a,b,!0))){var e=x&&!d&&Jd(a,b.from,b.to);if(e){for(var f=e.length-1;f>=1;--f)Ac(a,{from:e[f].from,to:e[f].to,text:[""]});e.length&&Ac(a,{from:e[0].from,to:e[0].to,text:b.text},c)}else Ac(a,b,c)}}function Ac(a,b,c){if(1!=b.text.length||""!=b.text[0]||!Hc(b.from,b.to)){var d=xc(a,b,c);Je(a,b,d,a.cm?a.cm.curOp.id:0/0),Dc(a,b,d,Gd(a,b));var e=[];we(a,function(a,c){c||-1!=pf(e,a.history)||(Pe(a.history,b),e.push(a.history)),Dc(a,b,null,Gd(a,b))})}}function Bc(a,b){if(!a.cm||!a.cm.state.suppressEdits){var c=a.history,d=("undo"==b?c.done:c.undone).pop();if(d){var e={changes:[],anchorBefore:d.anchorAfter,headBefore:d.headAfter,anchorAfter:d.anchorBefore,headAfter:d.headBefore,generation:c.generation};("undo"==b?c.undone:c.done).push(e),c.generation=d.generation||++c.maxGeneration;for(var f=ef(a,"beforeChange")||a.cm&&ef(a.cm,"beforeChange"),g=d.changes.length-1;g>=0;--g){var h=d.changes[g];if(h.origin=b,f&&!yc(a,h,!1))return("undo"==b?c.done:c.undone).length=0,void 0;e.changes.push(Ie(a,h));var i=g?xc(a,h,null):{anchor:d.anchorBefore,head:d.headBefore};Dc(a,h,i,Id(a,h));var j=[];we(a,function(a,b){b||-1!=pf(j,a.history)||(Pe(a.history,h),j.push(a.history)),Dc(a,h,null,Id(a,h))})}}}}function Cc(a,b){function c(a){return Gc(a.line+b,a.ch)}a.first+=b,a.cm&&Lb(a.cm,a.first,a.first,b),a.sel.head=c(a.sel.head),a.sel.anchor=c(a.sel.anchor),a.sel.from=c(a.sel.from),a.sel.to=c(a.sel.to)}function Dc(a,b,c,d){if(a.cm&&!a.cm.curOp)return Ib(a.cm,Dc)(a,b,c,d);if(b.to.linea.lastLine())){if(b.from.linef&&(b={from:b.from,to:Gc(f,ye(a,f).text.length),text:[b.text[0]],origin:b.origin}),b.removed=ze(a,b.from,b.to),c||(c=xc(a,b,null)),a.cm?Ec(a.cm,b,d,c):pe(a,b,d,c)}}function Ec(a,b,c,d){var e=a.doc,f=a.display,g=b.from,h=b.to,i=!1,j=g.line;a.options.lineWrapping||(j=Ce(Rd(e,ye(e,g.line))),e.iter(j,h.line+1,function(a){return a==f.maxLine?(i=!0,!0):void 0})),Ic(e.sel.head,b.from)||Ic(b.to,e.sel.head)||(a.curOp.cursorActivity=!0),pe(e,b,c,d,E(a)),a.options.lineWrapping||(e.iter(j,g.line+b.text.length,function(a){var b=K(e,a);b>f.maxLineLength&&(f.maxLine=a,f.maxLineLength=b,f.maxLineChanged=!0,i=!1)}),i&&(a.curOp.updateMaxLine=!0)),e.frontier=Math.min(e.frontier,g.line),eb(a,400);var k=b.text.length-(h.line-g.line)-1;if(Lb(a,g.line,h.line+1,k),ef(a,"change")){var l={from:g,to:h,text:b.text,removed:b.removed,origin:b.origin};if(a.curOp.textChanged){for(var m=a.curOp.textChanged;m.next;m=m.next);m.next=l}else a.curOp.textChanged=l}}function Fc(a,b,c,d,e){if(d||(d=c),Ic(d,c)){var f=d;d=c,c=f}"string"==typeof b&&(b=Kf(b)),zc(a,{from:c,to:d,text:b,origin:e},null)}function Gc(a,b){return this instanceof Gc?(this.line=a,this.ch=b,void 0):new Gc(a,b)}function Hc(a,b){return a.line==b.line&&a.ch==b.ch}function Ic(a,b){return a.linec?Gc(c,ye(a,c).text.length):Nc(b,ye(a,b.line).text.length)}function Nc(a,b){var c=a.ch;return null==c||c>b?Gc(a.line,b):0>c?Gc(a.line,0):a}function Oc(a,b){return b>=a.first&&b=f.ch:j.to>f.ch))){if(d&&($e(k,"beforeCursorEnter"),k.explicitlyCleared)){if(h.markedSpans){--i;continue}break}if(!k.atomic)continue;var l=k.find()[0>g?"from":"to"];if(Hc(l,f)&&(l.ch+=g,l.ch<0?l=l.line>a.first?Mc(a,Gc(l.line-1)):null:l.ch>h.text.length&&(l=l.line(window.innerHeight||document.documentElement.clientHeight)&&(e=!1),null!=e&&!p){var f=zf("div","\u200b",null,"position: absolute; top: "+(b.top-c.viewOffset)+"px; height: "+(b.bottom-b.top+gf)+"px; left: "+b.left+"px; width: 2px;");a.display.lineSpace.appendChild(f),f.scrollIntoView(e),a.display.lineSpace.removeChild(f)}}}function Vc(a,b,c,d){for(null==d&&(d=0);;){var e=!1,f=yb(a,b),g=c&&c!=b?yb(a,c):f,h=Xc(a,Math.min(f.left,g.left),Math.min(f.top,g.top)-d,Math.max(f.left,g.left),Math.max(f.bottom,g.bottom)+d),i=a.doc.scrollTop,j=a.doc.scrollLeft;if(null!=h.scrollTop&&(dc(a,h.scrollTop),Math.abs(a.doc.scrollTop-i)>1&&(e=!0)),null!=h.scrollLeft&&(ec(a,h.scrollLeft),Math.abs(a.doc.scrollLeft-j)>1&&(e=!0)),!e)return f}}function Wc(a,b,c,d,e){var f=Xc(a,b,c,d,e);null!=f.scrollTop&&dc(a,f.scrollTop),null!=f.scrollLeft&&ec(a,f.scrollLeft)}function Xc(a,b,c,d,e){var f=a.display,g=Db(a.display);0>c&&(c=0);var h=f.scroller.clientHeight-gf,i=f.scroller.scrollTop,j={},k=a.doc.height+jb(f),l=g>c,m=e>k-g;if(i>c)j.scrollTop=l?0:c;else if(e>i+h){var n=Math.min(c,(m?k:e)-h);n!=i&&(j.scrollTop=n)}var o=f.scroller.clientWidth-gf,p=f.scroller.scrollLeft;b+=f.gutters.offsetWidth,d+=f.gutters.offsetWidth;var q=f.gutters.offsetWidth,r=q+10>b;return p+q>b||r?(r&&(b=0),j.scrollLeft=Math.max(0,b-10-q)):d>o+p-3&&(j.scrollLeft=d+10-o),j}function Yc(a,b,c){a.curOp.updateScrollPos={scrollLeft:null==b?a.doc.scrollLeft:b,scrollTop:null==c?a.doc.scrollTop:c}}function Zc(a,b,c){var d=a.curOp.updateScrollPos||(a.curOp.updateScrollPos={scrollLeft:a.doc.scrollLeft,scrollTop:a.doc.scrollTop}),e=a.display.scroller;d.scrollTop=Math.max(0,Math.min(e.scrollHeight-e.clientHeight,d.scrollTop+c)),d.scrollLeft=Math.max(0,Math.min(e.scrollWidth-e.clientWidth,d.scrollLeft+b))}function $c(a,b,c,d){var f,e=a.doc;null==c&&(c="add"),"smart"==c&&(a.doc.mode.indent?f=hb(a,b):c="prev");var g=a.options.tabSize,h=ye(e,b),i=kf(h.text,null,g);h.stateAfter&&(h.stateAfter=null);var k,j=h.text.match(/^\s*/)[0];if(d||/\S/.test(h.text)){if("smart"==c&&(k=a.doc.mode.indent(f,h.text.slice(j.length),h.text),k==hf)){if(!d)return;c="prev"}}else k=0,c="not";"prev"==c?k=b>e.first?kf(ye(e,b-1).text,null,g):0:"add"==c?k=i+a.options.indentUnit:"subtract"==c?k=i-a.options.indentUnit:"number"==typeof c&&(k=i+c),k=Math.max(0,k);var l="",m=0;if(a.options.indentWithTabs)for(var n=Math.floor(k/g);n;--n)m+=g,l+=" ";k>m&&(l+=mf(k-m)),l!=j?Fc(a.doc,l,Gc(b,0),Gc(b,j.length),"+input"):e.sel.head.line==b&&e.sel.head.ch=a.first+a.size?j=!1:(f=b,i=ye(a,b))}function l(a){var b=(e?Zf:$f)(i,g,c,!0);if(null==b){if(a||!k())return j=!1;g=e?(0>c?Sf:Rf)(i):0>c?i.text.length:0}else g=b;return!0}var f=b.line,g=b.ch,h=c,i=ye(a,f),j=!0;if("char"==d)l();else if("column"==d)l(!0);else if("word"==d||"group"==d)for(var m=null,n="group"==d,o=!0;!(0>c)||l(!o);o=!1){var p=i.text.charAt(g)||"\n",q=vf(p)?"w":n&&"\n"==p?"n":!n||/\s/.test(p)?null:"p";if(!n||o||q||(q="s"),m&&m!=q){0>c&&(c=1,l());break}if(q&&(m=q),c>0&&!l(!o))break}var r=Tc(a,Gc(f,g),h,!0);return j||(r.hitSide=!0),r}function bd(a,b,c,d){var g,e=a.doc,f=b.left;if("page"==d){var h=Math.min(a.display.wrapper.clientHeight,window.innerHeight||document.documentElement.clientHeight);g=b.top+c*(h-(0>c?1.5:.5)*Db(a.display))}else"line"==d&&(g=c>0?b.bottom+3:b.top-3);for(;;){var i=Ab(a,f,g);if(!i.outside)break;if(0>c?0>=g:g>=e.height){i.hitSide=!0;break}g+=5*c}return i}function cd(a,b){var c=b.ch,d=b.ch;if(a){(b.xRel<0||d==a.length)&&c?--c:++d;for(var e=a.charAt(c),f=vf(e)?vf:/\s/.test(e)?function(a){return/\s/.test(a)}:function(a){return!/\s/.test(a)&&!vf(a)};c>0&&f(a.charAt(c-1));)--c;for(;dg;++g){var i=d(f[g]);if(i)return i}return!1}for(var e=0;e=b:f.to>b);(e||(e=[])).push({from:f.from,to:i?null:f.to,marker:g})}}return e}function Fd(a,b,c){if(a)for(var e,d=0;d=b:f.to>b);if(h||f.from==b&&"bookmark"==g.type&&(!c||f.marker.insertLeft)){var i=null==f.from||(g.inclusiveLeft?f.from<=b:f.from0&&h)for(var l=0;ll;++l)o.push(q);o.push(i)}return o}function Hd(a){for(var b=0;b=0&&0>=l||0>=k&&l>=0)&&(0>=k&&(Jc(j.to,c)||Ld(i.marker)-Kd(e))>0||k>=0&&(Jc(j.from,d)||Kd(i.marker)-Ld(e))<0))return!0}}}function Rd(a,b){for(var c;c=Od(b);)b=ye(a,c.find().from.line);return b}function Sd(a,b){var c=y&&b.markedSpans;if(c)for(var d,e=0;ea.options.maxHighlightLength?(g=!1,f&&ee(a,b,d,j.pos),j.pos=b.length,k=null):k=c.token(j,d),a.options.addModeClass){var l=z.innerMode(c,d).mode.name;l&&(k="m-"+(k?l+" "+k:l))}g&&i==k||(hi;){var d=e[h];d>a&&e.splice(h,1,a,e[h+1],d),h+=2,i=Math.min(a,d)}if(b)if(g.opaque)e.splice(c,h-c,a,b),h=c+2;else for(;h>c;c+=2){var f=e[c+1];e[c+1]=f?f+" "+b:b}})}return e}function de(a,b){return b.styles&&b.styles[0]==a.state.modeGen||(b.styles=ce(a,b,b.stateAfter=hb(a,Ce(b)))),b.styles}function ee(a,b,c,d){var e=a.doc.mode,f=new vd(b,a.options.tabSize);for(f.start=f.pos=d||0,""==b&&e.blankLine&&e.blankLine(c);!f.eol()&&f.pos<=a.options.maxHighlightLength;)e.token(f,c),f.start=f.pos}function he(a,b){if(!a)return null;for(;;){var c=a.match(/(?:^|\s+)line-(background-)?(\S+)/);if(!c)break;a=a.slice(0,c.index)+a.slice(c.index+c[0].length);var d=c[1]?"bgClass":"textClass";null==b[d]?b[d]=c[2]:new RegExp("(?:^|s)"+c[2]+"(?:$|s)").test(b[d])||(b[d]+=" "+c[2])}if(/^\s*$/.test(a))return null;var e=b.cm.options.addModeClass?ge:fe;return e[a]||(e[a]=a.replace(/\S+/g,"cm-$&"))}function ie(a,b,c,d){for(var e,f=b,i=!0;e=Od(f);)f=ye(a.doc,e.find().from.line);var j={pre:zf("pre"),col:0,pos:0,measure:null,measuredSomething:!1,cm:a,copyWidgets:d};do{f.text&&(i=!1),j.measure=f==b&&c,j.pos=0,j.addToken=j.measure?le:ke,(g||h)&&a.getOption("lineWrapping")&&(j.addToken=me(j.addToken));var k=oe(f,j,de(a,f));c&&f==b&&!j.measuredSomething&&(c[0]=j.pre.appendChild(Jf(a.display.measure)),j.measuredSomething=!0),k&&(f=ye(a.doc,k.to.line))}while(k);!c||j.measuredSomething||c[0]||(c[0]=j.pre.appendChild(i?zf("span","\xa0"):Jf(a.display.measure))),j.pre.firstChild||Sd(a.doc,b)||j.pre.appendChild(document.createTextNode("\xa0"));var l;if(c&&g&&(l=Fe(f))){var m=l.length-1;l[m].from==l[m].to&&--m;var n=l[m],o=l[m-1];if(n.from+1==n.to&&o&&n.leveli)?(null!=t.to&&l>t.to&&(l=t.to,n=""),u.className&&(m+=" "+u.className),u.startStyle&&t.from==i&&(o+=" "+u.startStyle),u.endStyle&&t.to==l&&(n+=" "+u.endStyle),u.title&&!p&&(p=u.title),u.collapsed&&(!q||Md(q.marker,u)<0)&&(q=t)):t.from>i&&l>t.from&&(l=t.from),"bookmark"==u.type&&t.from==i&&u.replacedWith&&r.push(u)}if(q&&(q.from||0)==i&&(ne(b,(null==q.to?h:q.to)-i,q.marker,null==q.from),null==q.to))return q.marker.find();if(!q&&r.length)for(var s=0;s=h)break;for(var v=Math.min(h,l);;){if(j){var w=i+j.length;if(!q){var x=w>v?j.slice(0,v-i):j;b.addToken(b,x,k?k+m:m,o,i+x.length==l?n:"",p)}if(w>=v){j=j.slice(v-i),i=v;break}i=w,o=""}j=e.slice(f,f=c[g++]),k=he(c[g++],b)}}else for(var g=1;gp;++p)r.push(new $d(j[p],f(p),e));r.push(new $d(m+k.text.slice(i.ch),n,e)),g(k,k.text.slice(0,h.ch)+j[0],f(0)),a.insert(h.line+1,r)}else if(1==j.length)g(k,k.text.slice(0,h.ch)+j[0]+l.text.slice(i.ch),f(0)),a.remove(h.line+1,o);else{g(k,k.text.slice(0,h.ch)+j[0],f(0)),g(l,m+l.text.slice(i.ch),n);for(var p=1,q=j.length-1,r=[];q>p;++p)r.push(new $d(j[p],f(p),e));o>1&&a.remove(h.line+1,o-1),a.insert(h.line+1,r)}else{for(var p=0,q=j.length-1,r=[];q>p;++p)r.push(new $d(j[p],f(p),e));g(l,l.text,n),o&&a.remove(h.line,o),r.length&&a.insert(h.line,r)}bf(a,"change",a,b),Rc(a,d.anchor,d.head,null,!0)}function qe(a){this.lines=a,this.parent=null;for(var b=0,c=a.length,d=0;c>b;++b)a[b].parent=this,d+=a[b].height;this.height=d}function re(a){this.children=a;for(var b=0,c=0,d=0,e=a.length;e>d;++d){var f=a[d];b+=f.chunkSize(),c+=f.height,f.parent=this}this.size=b,this.height=c,this.parent=null}function we(a,b,c){function d(a,e,f){if(a.linked)for(var g=0;gb){a=d;break}b-=e}return a.lines[b]}function ze(a,b,c){var d=[],e=b.line;return a.iter(b.line,c.line+1,function(a){var f=a.text;e==c.line&&(f=f.slice(0,c.ch)),e==b.line&&(f=f.slice(b.ch)),d.push(f),++e}),d}function Ae(a,b,c){var d=[];return a.iter(b,c,function(a){d.push(a.text)}),d}function Be(a,b){for(var c=b-a.height,d=a;d;d=d.parent)d.height+=c}function Ce(a){if(null==a.parent)return null;for(var b=a.parent,c=pf(b.lines,a),d=b.parent;d;b=d,d=d.parent)for(var e=0;d.children[e]!=b;++e)c+=d.children[e].chunkSize();return c+b.first}function De(a,b){var c=a.first;a:do{for(var d=0,e=a.children.length;e>d;++d){var f=a.children[d],g=f.height;if(g>b){a=f;continue a}b-=g,c+=f.chunkSize()}return c}while(!a.lines);for(var d=0,e=a.lines.length;e>d;++d){var h=a.lines[d],i=h.height;if(i>b)break;b-=i}return c+d}function Ee(a,b){b=Rd(a.doc,b);for(var c=0,d=b.parent,e=0;ef-a.cm.options.historyEventDelay||"*"==b.origin.charAt(0)))){var h=nf(g.changes);Hc(b.from,b.to)&&Hc(b.from,h.to)?h.to=vc(b):g.changes.push(Ie(a,b)),g.anchorAfter=c.anchor,g.headAfter=c.head}else for(g={changes:[Ie(a,b)],generation:e.generation,anchorBefore:a.sel.anchor,headBefore:a.sel.head,anchorAfter:c.anchor,headAfter:c.head},e.done.push(g);e.done.length>e.undoDepth;)e.done.shift();e.generation=++e.maxGeneration,e.lastTime=f,e.lastOp=d,e.lastOrigin=b.origin,h||$e(a,"historyAdded")}function Ke(a){if(!a)return null;for(var c,b=0;b-1&&(nf(g)[k]=i[k],delete i[k])}}return d}function Ne(a,b,c,d){c0}function ff(a){a.prototype.on=function(a,b){Ye(this,a,b)},a.prototype.off=function(a,b){Ze(this,a,b)}}function jf(){this.id=null}function kf(a,b,c,d,e){null==b&&(b=a.search(/[^\s\u00a0]/),-1==b&&(b=a.length));for(var f=d||0,g=e||0;b>f;++f)" "==a.charAt(f)?g+=c-g%c:++g;return g}function mf(a){for(;lf.length<=a;)lf.push(nf(lf)+" ");return lf[a]}function nf(a){return a[a.length-1]}function of(a){if(q)a.selectionStart=0,a.selectionEnd=a.value.length;else try{a.select()}catch(b){}}function pf(a,b){if(a.indexOf)return a.indexOf(b);for(var c=0,d=a.length;d>c;++c)if(a[c]==b)return c;return-1}function qf(a,b){function c(){}c.prototype=a;var d=new c;return b&&rf(b,d),d}function rf(a,b){b||(b={});for(var c in a)a.hasOwnProperty(c)&&(b[c]=a[c]);return b}function sf(a){for(var b=[],c=0;a>c;++c)b.push(void 0);return b}function tf(a){var b=Array.prototype.slice.call(arguments,1);return function(){return a.apply(null,b)}}function vf(a){return/\w/.test(a)||a>"\x80"&&(a.toUpperCase()!=a.toLowerCase()||uf.test(a))}function wf(a){for(var b in a)if(a.hasOwnProperty(b)&&a[b])return!1;return!0}function yf(a){return a.charCodeAt(0)>=768&&xf.test(a)}function zf(a,b,c,d){var e=document.createElement(a);if(c&&(e.className=c),d&&(e.style.cssText=d),"string"==typeof b)Cf(e,b);else if(b)for(var f=0;f0;--b)a.removeChild(a.firstChild);return a}function Bf(a,b){return Af(a).appendChild(b)}function Cf(a,b){d?(a.innerHTML="",a.appendChild(document.createTextNode(b))):a.textContent=b}function Df(a){return a.getBoundingClientRect()}function Ff(){return!1}function Hf(a){if(null!=Gf)return Gf;var b=zf("div",null,null,"width: 50px; height: 50px; overflow-x: scroll");return Bf(a,b),b.offsetWidth&&(Gf=b.offsetHeight-b.clientHeight),Gf||0}function Jf(a){if(null==If){var b=zf("span","\u200b");Bf(a,zf("span",[b,document.createTextNode("x")])),0!=a.firstChild.offsetHeight&&(If=b.offsetWidth<=1&&b.offsetHeight>2&&!c)}return If?zf("span","\u200b"):zf("span","\xa0",null,"display: inline-block; width: 1px; margin-right: -1px")}function Of(a,b,c,d){if(!a)return d(b,c,"ltr");for(var e=!1,f=0;fb||b==c&&g.to==b)&&(d(Math.max(g.from,b),Math.min(g.to,c),1==g.level?"rtl":"ltr"),e=!0)}e||d(b,c,"ltr")}function Pf(a){return a.level%2?a.to:a.from}function Qf(a){return a.level%2?a.from:a.to}function Rf(a){var b=Fe(a);return b?Pf(b[0]):0}function Sf(a){var b=Fe(a);return b?Qf(nf(b)):a.text.length}function Tf(a,b){var c=ye(a.doc,b),d=Rd(a.doc,c);d!=c&&(b=Ce(d));var e=Fe(d),f=e?e[0].level%2?Sf(d):Rf(d):0;return Gc(b,f)}function Uf(a,b){for(var c,d;c=Pd(d=ye(a.doc,b));)b=c.find().to.line;var e=Fe(d),f=e?e[0].level%2?Rf(d):Sf(d):d.text.length;return Gc(b,f)}function Vf(a,b,c){var d=a[0].level;return b==d?!0:c==d?!1:c>b}function Xf(a,b){Wf=null;for(var d,c=0;cb)return c;if(e.from==b||e.to==b){if(null!=d)return Vf(a,e.level,a[d].level)?(e.from!=e.to&&(Wf=d),c):(e.from!=e.to&&(Wf=c),d);d=c}}return d}function Yf(a,b,c,d){if(!d)return b+c;do b+=c;while(b>0&&yf(a.text.charAt(b)));return b}function Zf(a,b,c,d){var e=Fe(a);if(!e)return $f(a,b,c,d);for(var f=Xf(e,b),g=e[f],h=Yf(a,b,g.level%2?-c:c,d);;){if(h>g.from&&h0==g.level%2?g.to:g.from);if(g=e[f+=c],!g)return null;h=c>0==g.level%2?Yf(a,g.to,-1,d):Yf(a,g.from,1,d)}}function $f(a,b,c,d){var e=b+c;if(d)for(;e>0&&yf(a.text.charAt(e));)e+=c;return 0>e||e>a.text.length?null:e}var a=/gecko\/\d/i.test(navigator.userAgent),b=/MSIE \d/.test(navigator.userAgent),c=b&&(null==document.documentMode||document.documentMode<8),d=b&&(null==document.documentMode||document.documentMode<9),e=b&&(null==document.documentMode||document.documentMode<10),f=/Trident\/([7-9]|\d{2,})\./.test(navigator.userAgent),g=b||f,h=/WebKit\//.test(navigator.userAgent),i=h&&/Qt\/\d+\.\d+/.test(navigator.userAgent),j=/Chrome\//.test(navigator.userAgent),k=/Opera\//.test(navigator.userAgent),l=/Apple Computer/.test(navigator.vendor),m=/KHTML\//.test(navigator.userAgent),n=/Mac OS X 1\d\D([7-9]|\d\d)\D/.test(navigator.userAgent),o=/Mac OS X 1\d\D([8-9]|\d\d)\D/.test(navigator.userAgent),p=/PhantomJS/.test(navigator.userAgent),q=/AppleWebKit/.test(navigator.userAgent)&&/Mobile\/\w+/.test(navigator.userAgent),r=q||/Android|webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(navigator.userAgent),s=q||/Mac/.test(navigator.platform),t=/win/i.test(navigator.platform),u=k&&navigator.userAgent.match(/Version\/(\d*\.\d*)/);u&&(u=Number(u[1])),u&&u>=15&&(k=!1,h=!0);var Cb,Wb,Xb,v=s&&(i||k&&(null==u||12.11>u)),w=a||g&&!d,x=!1,y=!1,Fb=0,ac=0,fc=0,gc=null;g?gc=-.53:a?gc=15:j?gc=-.7:l&&(gc=-1/3);var kc,tc,oc=null,vc=z.changeEnd=function(a){return a.text?Gc(a.from.line+a.text.length-1,nf(a.text).length+(1==a.text.length?a.from.ch:0)):a.to};z.Pos=Gc,z.prototype={constructor:z,focus:function(){window.focus(),Qb(this),Nb(this)},setOption:function(a,b){var c=this.options,d=c[a];(c[a]!=b||"mode"==a)&&(c[a]=b,ed.hasOwnProperty(a)&&Ib(this,ed[a])(this,b,d))},getOption:function(a){return this.options[a]},getDoc:function(){return this.doc},addKeyMap:function(a,b){this.state.keyMaps[b?"push":"unshift"](a)},removeKeyMap:function(a){for(var b=this.state.keyMaps,c=0;c=d;++d)$c(this,d,a)}),getTokenAt:function(a,b){var c=this.doc;a=Mc(c,a);for(var d=hb(this,a.line,b),e=this.doc.mode,f=ye(c,a.line),g=new vd(f.text,this.options.tabSize);g.pos>1;if((f?b[2*f-1]:0)>=e)d=f;else{if(!(b[2*f+1]d&&(a=d,c=!0);var e=ye(this.doc,a);return vb(this,ye(this.doc,a),{top:0,left:0},b||"page").top+(c?e.height:0)},defaultTextHeight:function(){return Db(this.display)},defaultCharWidth:function(){return Eb(this.display)},setGutterMarker:Ib(null,function(a,b,c){return _c(this,a,function(a){var d=a.gutterMarkers||(a.gutterMarkers={});return d[b]=c,!c&&wf(d)&&(a.gutterMarkers=null),!0})}),clearGutter:Ib(null,function(a){var b=this,c=b.doc,d=c.first;c.iter(function(c){c.gutterMarkers&&c.gutterMarkers[a]&&(c.gutterMarkers[a]=null,Lb(b,d,d+1),wf(c.gutterMarkers)&&(c.gutterMarkers=null)),++d})}),addLineClass:Ib(null,function(a,b,c){return _c(this,a,function(a){var d="text"==b?"textClass":"background"==b?"bgClass":"wrapClass";if(a[d]){if(new RegExp("(?:^|\\s)"+c+"(?:$|\\s)").test(a[d]))return!1;a[d]+=" "+c}else a[d]=c;return!0})}),removeLineClass:Ib(null,function(a,b,c){return _c(this,a,function(a){var d="text"==b?"textClass":"background"==b?"bgClass":"wrapClass",e=a[d];if(!e)return!1;if(null==c)a[d]=null;else{var f=e.match(new RegExp("(?:^|\\s+)"+c+"(?:$|\\s+)"));if(!f)return!1;var g=f.index+f[0].length;a[d]=e.slice(0,f.index)+(f.index&&g!=e.length?" ":"")+e.slice(g)||null}return!0})}),addLineWidget:Ib(null,function(a,b,c){return Zd(this,a,b,c)}),removeLineWidget:function(a){a.clear()},lineInfo:function(a){if("number"==typeof a){if(!Oc(this.doc,a))return null;var b=a;if(a=ye(this.doc,a),!a)return null}else{var b=Ce(a);if(null==b)return null}return{line:b,handle:a,text:a.text,gutterMarkers:a.gutterMarkers,textClass:a.textClass,bgClass:a.bgClass,wrapClass:a.wrapClass,widgets:a.widgets}},getViewport:function(){return{from:this.display.showingFrom,to:this.display.showingTo}},addWidget:function(a,b,c,d,e){var f=this.display;a=yb(this,Mc(this.doc,a));var g=a.bottom,h=a.left;if(b.style.position="absolute",f.sizer.appendChild(b),"over"==d)g=a.top;else if("above"==d||"near"==d){var i=Math.max(f.wrapper.clientHeight,this.doc.height),j=Math.max(f.sizer.clientWidth,f.lineSpace.clientWidth);("above"==d||a.bottom+b.offsetHeight>i)&&a.top>b.offsetHeight?g=a.top-b.offsetHeight:a.bottom+b.offsetHeight<=i&&(g=a.bottom),h+b.offsetWidth>j&&(h=j-b.offsetWidth)}b.style.top=g+"px",b.style.left=b.style.right="","right"==e?(h=f.sizer.clientWidth-b.offsetWidth,b.style.right="0px"):("left"==e?h=0:"middle"==e&&(h=(f.sizer.clientWidth-b.offsetWidth)/2),b.style.left=h+"px"),c&&Wc(this,h,g,h+b.offsetWidth,g+b.offsetHeight)},triggerOnKeyDown:Ib(null,pc),triggerOnKeyPress:Ib(null,qc),triggerOnKeyUp:Ib(null,nc),execCommand:function(a){return pd.hasOwnProperty(a)?pd[a](this):void 0},findPosH:function(a,b,c,d){var e=1;0>b&&(e=-1,b=-b);for(var f=0,g=Mc(this.doc,a);b>f&&(g=ad(this.doc,g,e,c,d),!g.hitSide);++f);return g},moveH:Ib(null,function(a,b){var d,c=this.doc.sel;d=c.shift||c.extend||Hc(c.from,c.to)?ad(this.doc,c.head,a,b,this.options.rtlMoveVisually):0>a?c.from:c.to,Pc(this.doc,d,d,a)}),deleteH:Ib(null,function(a,b){var c=this.doc.sel;Hc(c.from,c.to)?Fc(this.doc,"",c.from,ad(this.doc,c.head,a,b,!1),"+delete"):Fc(this.doc,"",c.from,c.to,"+delete"),this.curOp.userSelChange=!0}),findPosV:function(a,b,c,d){var e=1,f=d;0>b&&(e=-1,b=-b);for(var g=0,h=Mc(this.doc,a);b>g;++g){var i=yb(this,h,"div");if(null==f?f=i.left:i.left=f,h=bd(this,i,e,c),h.hitSide)break}return h},moveV:Ib(null,function(a,b){var d,e,c=this.doc.sel;if(c.shift||c.extend||Hc(c.from,c.to)){var f=yb(this,c.head,"div");null!=c.goalColumn&&(f.left=c.goalColumn),d=bd(this,f,a,b),"page"==b&&Zc(this,0,xb(this,d,"div").top-f.top),e=f.left}else d=0>a?c.from:c.to;Pc(this.doc,d,d,a),null!=e&&(c.goalColumn=e)}),toggleOverwrite:function(a){(null==a||a!=this.state.overwrite)&&((this.state.overwrite=!this.state.overwrite)?this.display.cursor.className+=" CodeMirror-overwrite":this.display.cursor.className=this.display.cursor.className.replace(" CodeMirror-overwrite",""),$e(this,"overwriteToggle",this,this.state.overwrite))},hasFocus:function(){return document.activeElement==this.display.input},scrollTo:Ib(null,function(a,b){Yc(this,a,b)}),getScrollInfo:function(){var a=this.display.scroller,b=gf;return{left:a.scrollLeft,top:a.scrollTop,height:a.scrollHeight-b,width:a.scrollWidth-b,clientHeight:a.clientHeight-b,clientWidth:a.clientWidth-b}},scrollIntoView:Ib(null,function(a,b){null==a?a={from:this.doc.sel.head,to:null}:"number"==typeof a?a={from:Gc(a,0),to:null}:null==a.from&&(a={from:a,to:null}),a.to||(a.to=a.from),b||(b=0);var c=a;null!=a.from.line&&(this.curOp.scrollToPos={from:a.from,to:a.to,margin:b},c={from:yb(this,a.from),to:yb(this,a.to)});var d=Xc(this,Math.min(c.from.left,c.to.left),Math.min(c.from.top,c.to.top)-b,Math.max(c.from.right,c.to.right),Math.max(c.from.bottom,c.to.bottom)+b);Yc(this,d.scrollLeft,d.scrollTop)}),setSize:Ib(null,function(a,b){function c(a){return"number"==typeof a||/^\d+$/.test(String(a))?a+"px":a}null!=a&&(this.display.wrapper.style.width=c(a)),null!=b&&(this.display.wrapper.style.height=c(b)),this.options.lineWrapping&&(this.display.measureLineCache.length=this.display.measureLineCachePos=0),this.curOp.forceUpdate=!0,$e(this,"refresh",this)}),operation:function(a){return Kb(this,a)},refresh:Ib(null,function(){var a=this.display.cachedTextHeight;sb(this),Yc(this,this.doc.scrollLeft,this.doc.scrollTop),Lb(this),(null==a||Math.abs(a-Db(this.display))>.5)&&F(this),$e(this,"refresh",this)}),swapDoc:Ib(null,function(a){var b=this.doc;return b.cm=null,xe(this,a),sb(this),Pb(this,!0),Yc(this,a.scrollLeft,a.scrollTop),bf(this,"swapDoc",this,b),b}),getInputField:function(){return this.display.input},getWrapperElement:function(){return this.display.wrapper},getScrollerElement:function(){return this.display.scroller},getGutterElement:function(){return this.display.gutters}},ff(z);var ed=z.optionHandlers={},fd=z.defaults={},hd=z.Init={toString:function(){return"CodeMirror.Init"}};gd("value","",function(a,b){a.setValue(b)},!0),gd("mode",null,function(a,b){a.doc.modeOption=b,B(a)},!0),gd("indentUnit",2,B,!0),gd("indentWithTabs",!1),gd("smartIndent",!0),gd("tabSize",4,function(a){C(a),sb(a),Lb(a)},!0),gd("specialChars",/[\t\u0000-\u0019\u00ad\u200b\u2028\u2029\ufeff]/g,function(a,b){a.options.specialChars=new RegExp(b.source+(b.test(" ")?"":"| "),"g"),a.refresh()},!0),gd("specialCharPlaceholder",je,function(a){a.refresh()},!0),gd("electricChars",!0),gd("rtlMoveVisually",!t),gd("wholeLineUpdateBefore",!0),gd("theme","default",function(a){H(a),I(a)},!0),gd("keyMap","default",G),gd("extraKeys",null),gd("onKeyEvent",null),gd("onDragEvent",null),gd("lineWrapping",!1,D,!0),gd("gutters",[],function(a){M(a.options),I(a)},!0),gd("fixedGutter",!0,function(a,b){a.display.gutters.style.left=b?S(a.display)+"px":"0",a.refresh()},!0),gd("coverGutterNextToScrollbar",!1,N,!0),gd("lineNumbers",!1,function(a){M(a.options),I(a)},!0),gd("firstLineNumber",1,I,!0),gd("lineNumberFormatter",function(a){return a},I,!0),gd("showCursorWhenSelecting",!1,ab,!0),gd("resetSelectionOnContextMenu",!0),gd("readOnly",!1,function(a,b){"nocursor"==b?(sc(a),a.display.input.blur(),a.display.disabled=!0):(a.display.disabled=!1,b||Pb(a,!0))}),gd("disableInput",!1,function(a,b){b||Pb(a,!0)},!0),gd("dragDrop",!0),gd("cursorBlinkRate",530),gd("cursorScrollMargin",0),gd("cursorHeight",1),gd("workTime",100),gd("workDelay",100),gd("flattenSpans",!0,C,!0),gd("addModeClass",!1,C,!0),gd("pollInterval",100),gd("undoDepth",40,function(a,b){a.doc.history.undoDepth=b}),gd("historyEventDelay",500),gd("viewportMargin",10,function(a){a.refresh()},!0),gd("maxHighlightLength",1e4,C,!0),gd("crudeMeasuringFrom",1e4),gd("moveInputWithCursor",!0,function(a,b){b||(a.display.inputDiv.style.top=a.display.inputDiv.style.left=0)}),gd("tabindex",null,function(a,b){a.display.input.tabIndex=b||""}),gd("autofocus",null);var id=z.modes={},jd=z.mimeModes={};z.defineMode=function(a,b){if(z.defaults.mode||"null"==a||(z.defaults.mode=a),arguments.length>2){b.dependencies=[];for(var c=2;c0&&b.ch=this.string.length},sol:function(){return this.pos==this.lineStart},peek:function(){return this.string.charAt(this.pos)||void 0},next:function(){return this.posb},eatSpace:function(){for(var a=this.pos;/[\s\u00a0]/.test(this.string.charAt(this.pos));)++this.pos;return this.pos>a},skipToEnd:function(){this.pos=this.string.length},skipTo:function(a){var b=this.string.indexOf(a,this.pos);return b>-1?(this.pos=b,!0):void 0},backUp:function(a){this.pos-=a},column:function(){return this.lastColumnPos0?null:(f&&b!==!1&&(this.pos+=f[0].length),f)}var d=function(a){return c?a.toLowerCase():a},e=this.string.substr(this.pos,a.length);return d(e)==d(a)?(b!==!1&&(this.pos+=a.length),!0):void 0},current:function(){return this.string.slice(this.start,this.pos)},hideFirstChars:function(a,b){this.lineStart+=a;try{return b()}finally{this.lineStart-=a}}},z.StringStream=vd,z.TextMarker=wd,ff(wd),wd.prototype.clear=function(){if(!this.explicitlyCleared){var a=this.doc.cm,b=a&&!a.curOp;if(b&&Gb(a),ef(this,"clear")){var c=this.find();c&&bf(this,"clear",c.from,c.to)}for(var d=null,e=null,f=0;fa.display.maxLineLength&&(a.display.maxLine=i,a.display.maxLineLength=j,a.display.maxLineChanged=!0)}null!=d&&a&&Lb(a,d,e+1),this.lines.length=0,this.explicitlyCleared=!0,this.atomic&&this.doc.cantEdit&&(this.doc.cantEdit=!1,a&&Sc(a)),bf(a,"markerCleared",a,this),b&&Hb(a)}},wd.prototype.find=function(a){for(var b,c,d=0;d=b.display.showingFrom&&a.linec;++c){var e=this.lines[c];this.height-=e.height,ae(e),bf(e,"delete")}this.lines.splice(a,b)},collapse:function(a){a.splice.apply(a,[a.length,0].concat(this.lines))},insertInner:function(a,b,c){this.height+=c,this.lines=this.lines.slice(0,a).concat(b).concat(this.lines.slice(a));for(var d=0,e=b.length;e>d;++d)b[d].parent=this},iterN:function(a,b,c){for(var d=a+b;d>a;++a)if(c(this.lines[a]))return!0}},re.prototype={chunkSize:function(){return this.size},removeInner:function(a,b){this.size-=b;for(var c=0;ca){var f=Math.min(b,e-a),g=d.height;if(d.removeInner(a,f),this.height-=g-d.height,e==f&&(this.children.splice(c--,1),d.parent=null),0==(b-=f))break;a=0}else a-=e}if(this.size-b<25){var h=[];this.collapse(h),this.children=[new qe(h)],this.children[0].parent=this}},collapse:function(a){for(var b=0,c=this.children.length;c>b;++b)this.children[b].collapse(a)},insertInner:function(a,b,c){this.size+=b.length,this.height+=c;for(var d=0,e=this.children.length;e>d;++d){var f=this.children[d],g=f.chunkSize();if(g>=a){if(f.insertInner(a,b,c),f.lines&&f.lines.length>50){for(;f.lines.length>50;){var h=f.lines.splice(f.lines.length-25,25),i=new qe(h);f.height-=i.height,this.children.splice(d+1,0,i),i.parent=this}this.maybeSpill()}break}a-=g}},maybeSpill:function(){if(!(this.children.length<=10)){var a=this;do{var b=a.children.splice(a.children.length-5,5),c=new re(b);if(a.parent){a.size-=c.size,a.height-=c.height;var e=pf(a.parent.children,a);a.parent.children.splice(e+1,0,c)}else{var d=new re(a.children);d.parent=a,a.children=[d,c],a=d}c.parent=a.parent}while(a.children.length>10);a.parent.maybeSpill()}},iterN:function(a,b,c){for(var d=0,e=this.children.length;e>d;++d){var f=this.children[d],g=f.chunkSize();if(g>a){var h=Math.min(b,g-a);if(f.iterN(a,h,c))return!0;if(0==(b-=h))break;a=0}else a-=g}}};var se=0,te=z.Doc=function(a,b,c){if(!(this instanceof te))return new te(a,b,c);null==c&&(c=0),re.call(this,[new qe([new $d("",null)])]),this.first=c,this.scrollTop=this.scrollLeft=0,this.cantEdit=!1,this.history=Ge(),this.cleanGeneration=1,this.frontier=c;var d=Gc(c,0);this.sel={from:d,to:d,head:d,anchor:d,shift:!1,extend:!1,goalColumn:null},this.id=++se,this.modeOption=b,"string"==typeof a&&(a=Kf(a)),pe(this,{from:d,to:d,text:a},null,{head:d,anchor:d})};te.prototype=qf(re.prototype,{constructor:te,iter:function(a,b,c){c?this.iterN(a-this.first,b-a,c):this.iterN(this.first,this.first+this.size,a)},insert:function(a,b){for(var c=0,d=0,e=b.length;e>d;++d)c+=b[d].height;this.insertInner(a-this.first,b,c)},remove:function(a,b){this.removeInner(a-this.first,b)},getValue:function(a){var b=Ae(this,this.first,this.first+this.size);return a===!1?b:b.join(a||"\n")},setValue:function(a){var b=Gc(this.first,0),c=this.first+this.size-1;zc(this,{from:b,to:Gc(c,ye(this,c).text.length),text:Kf(a),origin:"setValue"},{head:b,anchor:b},!0)},replaceRange:function(a,b,c,d){b=Mc(this,b),c=c?Mc(this,c):b,Fc(this,a,b,c,d)},getRange:function(a,b,c){var d=ze(this,Mc(this,a),Mc(this,b));return c===!1?d:d.join(c||"\n")},getLine:function(a){var b=this.getLineHandle(a);return b&&b.text},setLine:function(a,b){Oc(this,a)&&Fc(this,b,Gc(a,0),Mc(this,Gc(a)))},removeLine:function(a){a?Fc(this,"",Mc(this,Gc(a-1)),Mc(this,Gc(a))):Fc(this,"",Gc(0,0),Mc(this,Gc(1,0)))},getLineHandle:function(a){return Oc(this,a)?ye(this,a):void 0},getLineNumber:function(a){return Ce(a)},getLineHandleVisualStart:function(a){return"number"==typeof a&&(a=ye(this,a)),Rd(this,a)},lineCount:function(){return this.size},firstLine:function(){return this.first},lastLine:function(){return this.first+this.size-1},clipPos:function(a){return Mc(this,a)},getCursor:function(a){var c,b=this.sel;return c=null==a||"head"==a?b.head:"anchor"==a?b.anchor:"end"==a||a===!1?b.to:b.from,Kc(c)},somethingSelected:function(){return!Hc(this.sel.head,this.sel.anchor)},setCursor:Jb(function(a,b,c){var d=Mc(this,"number"==typeof a?Gc(a,b||0):a);c?Pc(this,d):Rc(this,d,d)}),setSelection:Jb(function(a,b,c){Rc(this,Mc(this,a),Mc(this,b||a),c)}),extendSelection:Jb(function(a,b,c){Pc(this,Mc(this,a),b&&Mc(this,b),c)}),getSelection:function(a){return this.getRange(this.sel.from,this.sel.to,a)},replaceSelection:function(a,b,c){zc(this,{from:this.sel.from,to:this.sel.to,text:Kf(a),origin:c},b||"around")},undo:Jb(function(){Bc(this,"undo")}),redo:Jb(function(){Bc(this,"redo")}),setExtending:function(a){this.sel.extend=a},historySize:function(){var a=this.history;return{undo:a.done.length,redo:a.undone.length}},clearHistory:function(){this.history=Ge(this.history.maxGeneration)},markClean:function(){this.cleanGeneration=this.changeGeneration(!0)},changeGeneration:function(a){return a&&(this.history.lastOp=this.history.lastOrigin=null),this.history.generation},isClean:function(a){return this.history.generation==(a||this.cleanGeneration)},getHistory:function(){return{done:Me(this.history.done),undone:Me(this.history.undone)}},setHistory:function(a){var b=this.history=Ge(this.history.maxGeneration);b.done=a.done.slice(0),b.undone=a.undone.slice(0)},markText:function(a,b,c){return yd(this,Mc(this,a),Mc(this,b),c,"range")},setBookmark:function(a,b){var c={replacedWith:b&&(null==b.nodeType?b.widget:b),insertLeft:b&&b.insertLeft,clearWhenEmpty:!1};return a=Mc(this,a),yd(this,a,a,c,"bookmark")},findMarksAt:function(a){a=Mc(this,a);var b=[],c=ye(this,a.line).markedSpans;if(c)for(var d=0;d=a.ch)&&b.push(e.marker.parent||e.marker)}return b},findMarks:function(a,b){a=Mc(this,a),b=Mc(this,b);var c=[],d=a.line;return this.iter(a.line,b.line+1,function(e){var f=e.markedSpans;if(f)for(var g=0;gh.to||null==h.from&&d!=a.line||d==b.line&&h.from>b.ch||c.push(h.marker.parent||h.marker)}++d}),c},getAllMarks:function(){var a=[];return this.iter(function(b){var c=b.markedSpans;if(c)for(var d=0;da?(b=a,!0):(a-=e,++c,void 0)}),Mc(this,Gc(c,b))},indexFromPos:function(a){a=Mc(this,a);var b=a.ch;return a.lineb&&(b=a.from),null!=a.to&&a.to=8208&&8212>=c}:h&&(Ff=function(a,b){if(b>1&&45==a.charCodeAt(b-1)){if(/\w/.test(a.charAt(b-2))&&/[^\-?\.]/.test(a.charAt(b)))return!0;if(b>2&&/[\d\.,]/.test(a.charAt(b-2))&&/[\d\.,]/.test(a.charAt(b)))return!1}return/[~!#%&*)=+}\]\\|\"\.>,:;][({[<]|-[^\-?\.\u2010-\u201f\u2026]|\?[\w~`@#$%\^&*(_=+{[|><]|\u2026[\w~`@#$%\^&*(_=+{[><]/.test(a.slice(b-1,b+1))});var Gf,If,Kf=3!="\n\nb".split(/\n/).length?function(a){for(var b=0,c=[],d=a.length;d>=b;){var e=a.indexOf("\n",b);-1==e&&(e=a.length);var f=a.slice(b,"\r"==a.charAt(e-1)?e-1:e),g=f.indexOf("\r");-1!=g?(c.push(f.slice(0,g)),b+=g+1):(c.push(f),b=e+1)}return c}:function(a){return a.split(/\r\n?|\n/)};z.splitLines=Kf;var Lf=window.getSelection?function(a){try{return a.selectionStart!=a.selectionEnd}catch(b){return!1}}:function(a){try{var b=a.ownerDocument.selection.createRange()}catch(c){}return b&&b.parentElement()==a?0!=b.compareEndPoints("StartToEnd",b):!1},Mf=function(){var a=zf("div");return"oncopy"in a?!0:(a.setAttribute("oncopy","return;"),"function"==typeof a.oncopy)}(),Nf={3:"Enter",8:"Backspace",9:"Tab",13:"Enter",16:"Shift",17:"Ctrl",18:"Alt",19:"Pause",20:"CapsLock",27:"Esc",32:"Space",33:"PageUp",34:"PageDown",35:"End",36:"Home",37:"Left",38:"Up",39:"Right",40:"Down",44:"PrintScrn",45:"Insert",46:"Delete",59:";",61:"=",91:"Mod",92:"Mod",93:"Mod",107:"=",109:"-",127:"Delete",173:"-",186:";",187:"=",188:",",189:"-",190:".",191:"/",192:"`",219:"[",220:"\\",221:"]",222:"'",63232:"Up",63233:"Down",63234:"Left",63235:"Right",63272:"Delete",63273:"Home",63275:"End",63276:"PageUp",63277:"PageDown",63302:"Insert"};z.keyNames=Nf,function(){for(var a=0;10>a;a++)Nf[a+48]=Nf[a+96]=String(a);for(var a=65;90>=a;a++)Nf[a]=String.fromCharCode(a);for(var a=1;12>=a;a++)Nf[a+111]=Nf[a+63235]="F"+a}();var Wf,_f=function(){function c(c){return 255>=c?a.charAt(c):c>=1424&&1524>=c?"R":c>=1536&&1791>=c?b.charAt(c-1536):c>=1792&&2220>=c?"r":"L"}var a="bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLL",b="rrrrrrrrrrrr,rNNmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmrrrrrrrnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmNmmmmrrrrrrrrrrrrrrrrrr",d=/[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/,e=/[stwN]/,f=/[LRr]/,g=/[Lb1n]/,h=/[1n]/,i="L";return function(a){if(!d.test(a))return!1;for(var l,b=a.length,j=[],k=0;b>k;++k)j.push(l=c(a.charCodeAt(k)));for(var k=0,m=i;b>k;++k){var l=j[k];"m"==l?j[k]=m:m=l}for(var k=0,n=i;b>k;++k){var l=j[k];"1"==l&&"r"==n?j[k]="n":f.test(l)&&(n=l,"r"==l&&(j[k]="R"))}for(var k=1,m=j[0];b-1>k;++k){var l=j[k];"+"==l&&"1"==m&&"1"==j[k+1]?j[k]="1":","!=l||m!=j[k+1]||"1"!=m&&"n"!=m||(j[k]=m),m=l}for(var k=0;b>k;++k){var l=j[k];if(","==l)j[k]="N";else if("%"==l){for(var o=k+1;b>o&&"%"==j[o];++o);for(var p=k&&"!"==j[k-1]||b>o&&"1"==j[o]?"1":"N",q=k;o>q;++q)j[q]=p;k=o-1}}for(var k=0,n=i;b>k;++k){var l=j[k];"L"==n&&"1"==l?j[k]="L":f.test(l)&&(n=l)}for(var k=0;b>k;++k)if(e.test(j[k])){for(var o=k+1;b>o&&e.test(j[o]);++o);for(var r="L"==(k?j[k-1]:i),s="L"==(b>o?j[o]:i),p=r||s?"L":"R",q=k;o>q;++q)j[q]=p;k=o-1}for(var u,t=[],k=0;b>k;)if(g.test(j[k])){var v=k;for(++k;b>k&&g.test(j[k]);++k);t.push({from:v,to:k,level:0})}else{var w=k,x=t.length;for(++k;b>k&&"L"!=j[k];++k);for(var q=w;k>q;)if(h.test(j[q])){q>w&&t.splice(x,0,{from:w,to:q,level:1});var y=q;for(++q;k>q&&h.test(j[q]);++q);t.splice(x,0,{from:y,to:q,level:2}),w=q}else++q;k>w&&t.splice(x,0,{from:w,to:k,level:1})}return 1==t[0].level&&(u=a.match(/^\s+/))&&(t[0].from=u[0].length,t.unshift({from:0,to:u[0].length,level:0})),1==nf(t).level&&(u=a.match(/\s+$/))&&(nf(t).to-=u[0].length,t.push({from:b-u[0].length,to:b,level:0})),t[0].level!=nf(t).level&&t.push({from:b,to:b,level:t[0].level}),t}}();return z.version="3.22.1",z}(),CodeMirror.defineMode("javascript",function(a,b){function k(a){for(var c,b=!1,d=!1;null!=(c=a.next());){if(!b){if("/"==c&&!d)return;"["==c?d=!0:d&&"]"==c&&(d=!1)}b=!b&&"\\"==c}}function n(a,b,c){return l=a,m=c,b}function o(a,b){var c=a.next();if('"'==c||"'"==c)return b.tokenize=p(c),b.tokenize(a,b);if("."==c&&a.match(/^\d+(?:[eE][+\-]?\d+)?/))return n("number","number");if("."==c&&a.match(".."))return n("spread","meta");if(/[\[\]{}\(\),;\:\.]/.test(c))return n(c);if("="==c&&a.eat(">"))return n("=>","operator");if("0"==c&&a.eat(/x/i))return a.eatWhile(/[\da-f]/i),n("number","number");if(/\d/.test(c))return a.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/),n("number","number");if("/"==c)return a.eat("*")?(b.tokenize=q,q(a,b)):a.eat("/")?(a.skipToEnd(),n("comment","comment")):"operator"==b.lastType||"keyword c"==b.lastType||"sof"==b.lastType||/^[\[{}\(,;:]$/.test(b.lastType)?(k(a),a.eatWhile(/[gimy]/),n("regexp","string-2")):(a.eatWhile(i),n("operator","operator",a.current()));if("`"==c)return b.tokenize=r,r(a,b);if("#"==c)return a.skipToEnd(),n("error","error");if(i.test(c))return a.eatWhile(i),n("operator","operator",a.current());a.eatWhile(/[\w\$_]/);var d=a.current(),e=h.propertyIsEnumerable(d)&&h[d];return e&&"."!=b.lastType?n(e.type,e.style,d):n("variable","variable",d)}function p(a){return function(b,c){var f,d=!1;if(e&&"@"==b.peek()&&b.match(j))return c.tokenize=o,n("jsonld-keyword","meta");for(;null!=(f=b.next())&&(f!=a||d);)d=!d&&"\\"==f;return d||(c.tokenize=o),n("string","string")}}function q(a,b){for(var d,c=!1;d=a.next();){if("/"==d&&c){b.tokenize=o;break}c="*"==d}return n("comment","comment")}function r(a,b){for(var d,c=!1;null!=(d=a.next());){if(!c&&("`"==d||"$"==d&&a.eat("{"))){b.tokenize=o;break}c=!c&&"\\"==d}return n("quasi","string-2",a.current())}function t(a,b){b.fatArrowAt&&(b.fatArrowAt=null);var c=a.string.indexOf("=>",a.start);if(!(0>c)){for(var d=0,e=!1,f=c-1;f>=0;--f){var g=a.string.charAt(f),h=s.indexOf(g);if(h>=0&&3>h){if(!d){++f;break}if(0==--d)break}else if(h>=3&&6>h)++d;else if(/[$\w]/.test(g))e=!0;else if(e&&!d){++f;break}}e&&!d&&(b.fatArrowAt=f)}}function v(a,b,c,d,e,f){this.indented=a,this.column=b,this.type=c,this.prev=e,this.info=f,null!=d&&(this.align=d)}function w(a,b){for(var c=a.localVars;c;c=c.next)if(c.name==b)return!0;for(var d=a.context;d;d=d.prev)for(var c=d.vars;c;c=c.next)if(c.name==b)return!0}function x(a,b,c,d,e){var g=a.cc;for(y.state=a,y.stream=e,y.marked=null,y.cc=g,a.lexical.hasOwnProperty("align")||(a.lexical.align=!0);;){var h=g.length?g.pop():f?J:I;if(h(c,d)){for(;g.length&&g[g.length-1].lex;)g.pop()();return y.marked?y.marked:"variable"==c&&w(a,d)?"variable-2":b}}}function z(){for(var a=arguments.length-1;a>=0;a--)y.cc.push(arguments[a])}function A(){return z.apply(null,arguments),!0}function B(a){function c(b){for(var c=b;c;c=c.next)if(c.name==a)return!0;return!1}var d=y.state;if(d.context){if(y.marked="def",c(d.localVars))return;d.localVars={name:a,next:d.localVars}}else{if(c(d.globalVars))return;b.globalVars&&(d.globalVars={name:a,next:d.globalVars})}}function D(){y.state.context={prev:y.state.context,vars:y.state.localVars},y.state.localVars=C}function E(){y.state.localVars=y.state.context.vars,y.state.context=y.state.context.prev}function F(a,b){var c=function(){var c=y.state,d=c.indented;"stat"==c.lexical.type&&(d=c.lexical.indented),c.lexical=new v(d,y.stream.column(),a,null,c.lexical,b)};return c.lex=!0,c}function G(){var a=y.state;a.lexical.prev&&(")"==a.lexical.type&&(a.indented=a.lexical.indented),a.lexical=a.lexical.prev)}function H(a){return function(b){return b==a?A():";"==a?z():A(arguments.callee)}}function I(a,b){return"var"==a?A(F("vardef",b.length),cb,H(";"),G):"keyword a"==a?A(F("form"),J,I,G):"keyword b"==a?A(F("form"),I,G):"{"==a?A(F("}"),_,G):";"==a?A():"if"==a?A(F("form"),J,I,G,hb):"function"==a?A(nb):"for"==a?A(F("form"),ib,I,G):"variable"==a?A(F("stat"),U):"switch"==a?A(F("form"),J,F("}","switch"),H("{"),_,G,G):"case"==a?A(J,H(":")):"default"==a?A(H(":")):"catch"==a?A(F("form"),D,H("("),ob,H(")"),I,G,E):"module"==a?A(F("form"),D,sb,E,G):"class"==a?A(F("form"),pb,rb,G):"export"==a?A(F("form"),tb,G):"import"==a?A(F("form"),ub,G):z(F("stat"),J,H(";"),G)}function J(a){return L(a,!1)}function K(a){return L(a,!0)}function L(a,b){if(y.state.fatArrowAt==y.stream.start){var c=b?T:S;if("("==a)return A(D,F(")"),Z(db,")"),G,H("=>"),c,E);if("variable"==a)return z(D,db,H("=>"),c,E)}var d=b?P:O;return u.hasOwnProperty(a)?A(d):"function"==a?A(nb):"keyword c"==a?A(b?N:M):"("==a?A(F(")"),M,zb,H(")"),G,d):"operator"==a||"spread"==a?A(b?K:J):"["==a?A(F("]"),xb,G,d):"{"==a?$(W,"}",null,d):A()}function M(a){return a.match(/[;\}\)\],]/)?z():z(J)}function N(a){return a.match(/[;\}\)\],]/)?z():z(K)}function O(a,b){return","==a?A(J):P(a,b,!1)}function P(a,b,c){var d=0==c?O:P,e=0==c?J:K;return"=>"==b?A(D,c?T:S,E):"operator"==a?/\+\+|--/.test(b)?A(d):"?"==b?A(J,H(":"),e):A(e):"quasi"==a?(y.cc.push(d),Q(b)):";"!=a?"("==a?$(K,")","call",d):"."==a?A(V,d):"["==a?A(F("]"),M,H("]"),G,d):void 0:void 0}function Q(a){return"${"!=a.slice(a.length-2)?A():A(J,R)}function R(a){return"}"==a?(y.marked="string-2",y.state.tokenize=r,A()):void 0}function S(a){return t(y.stream,y.state),"{"==a?z(I):z(J)}function T(a){return t(y.stream,y.state),"{"==a?z(I):z(K)}function U(a){return":"==a?A(G,I):z(O,H(";"),G)}function V(a){return"variable"==a?(y.marked="property",A()):void 0}function W(a,b){if("variable"==a){if(y.marked="property","get"==b||"set"==b)return A(X)}else if("number"==a||"string"==a)y.marked=e?"property":a+" property";else if("["==a)return A(J,H("]"),Y);return u.hasOwnProperty(a)?A(Y):void 0}function X(a){return"variable"!=a?z(Y):(y.marked="property",A(nb))}function Y(a){return":"==a?A(K):"("==a?z(nb):void 0}function Z(a,b){function c(d){if(","==d){var e=y.state.lexical;return"call"==e.info&&(e.pos=(e.pos||0)+1),A(a,c)}return d==b?A():A(H(b))}return function(d){return d==b?A():z(a,c)}}function $(a,b,c){for(var d=3;d!?|~^]/,j=/^@(context|id|value|language|type|container|list|set|reverse|index|base|vocab|graph)"/,s="([{}])",u={atom:!0,number:!0,variable:!0,string:!0,regexp:!0,"this":!0,"jsonld-keyword":!0},y={state:null,column:null,marked:null,cc:null},C={name:"this",next:{name:"arguments"}};return G.lex=!0,{startState:function(a){var d={tokenize:o,lastType:"sof",cc:[],lexical:new v((a||0)-c,0,"block",!1),localVars:b.localVars,context:b.localVars&&{vars:b.localVars},indented:0};return b.globalVars&&(d.globalVars=b.globalVars),d},token:function(a,b){if(a.sol()&&(b.lexical.hasOwnProperty("align")||(b.lexical.align=!1),b.indented=a.indentation(),t(a,b)),b.tokenize!=q&&a.eatSpace())return null;var c=b.tokenize(a,b);return"comment"==l?c:(b.lastType="operator"!=l||"++"!=m&&"--"!=m?l:"incdec",x(b,c,l,m,a))},indent:function(a,e){if(a.tokenize==q)return CodeMirror.Pass;if(a.tokenize!=o)return 0;for(var f=e&&e.charAt(0),g=a.lexical,h=a.cc.length-1;h>=0;--h){var i=a.cc[h];if(i==G)g=g.prev;else if(i!=hb)break}"stat"==g.type&&"}"==f&&(g=g.prev),d&&")"==g.type&&"stat"==g.prev.type&&(g=g.prev);var j=g.type,k=f==j;return"vardef"==j?g.indented+("operator"==a.lastType||","==a.lastType?g.info+1:0):"form"==j&&"{"==f?g.indented:"form"==j?g.indented+c:"stat"==j?g.indented+("operator"==a.lastType||","==a.lastType?d||c:0):"switch"!=g.info||k||0==b.doubleIndentSwitch?g.align?g.column+(k?0:1):g.indented+(k?0:c):g.indented+(/^(?:case|default)\b/.test(e)?c:2*c)},electricChars:":{}",blockCommentStart:f?null:"/*",blockCommentEnd:f?null:"*/",lineComment:f?null:"//",fold:"brace",helperType:f?"json":"javascript",jsonldMode:e,jsonMode:f}}),CodeMirror.defineMIME("text/javascript","javascript"),CodeMirror.defineMIME("text/ecmascript","javascript"),CodeMirror.defineMIME("application/javascript","javascript"),CodeMirror.defineMIME("application/ecmascript","javascript"),CodeMirror.defineMIME("application/json",{name:"javascript",json:!0}),CodeMirror.defineMIME("application/x-json",{name:"javascript",json:!0}),CodeMirror.defineMIME("application/ld+json",{name:"javascript",jsonld:!0}),CodeMirror.defineMIME("text/typescript",{name:"javascript",typescript:!0}),CodeMirror.defineMIME("application/typescript",{name:"javascript",typescript:!0}),function(){function d(a,d,e){function r(d,e,f){if(d.text){var h=m?0:d.text.length-1,i=m?d.text.length:-1;if(d.text.length>g)return null;for(null!=f&&(h=f+n);h!=i;h+=n){var j=d.text.charAt(h);if(q.test(j)&&a.getTokenTypeAt(b(e,h+1))==o){var k=c[j];if(">"==k.charAt(1)==m)p.push(j);else{if(p.pop()!=k.charAt(0))return{pos:h,match:!1};if(!p.length)return{pos:h,match:!0}}}}}}var f=a.state.matchBrackets,g=f&&f.maxScanLineLength||1e4,h=f&&f.maxScanLines||100,i=d||a.getCursor(),j=a.getLineHandle(i.line),k=i.ch-1,l=k>=0&&c[j.text.charAt(k)]||c[j.text.charAt(++k)];if(!l)return null;var m=">"==l.charAt(1),n=m?1:-1;if(e&&m!=(k==i.ch))return null;for(var t,o=a.getTokenTypeAt(b(i.line,k+1)),p=[j.text.charAt(k)],q=/[(){}[\]]/,s=i.line,u=m?Math.min(s+h,a.lineCount()):Math.max(-1,s-h);s!=u&&!(t=s==i.line?r(j,s,k):r(a.getLineHandle(s),s));s+=n);return{from:b(i.line,k),to:t&&b(s,t.pos),match:t&&t.match,forward:m}}function e(c,e){var f=c.state.matchBrackets.maxHighlightLineLength||1e3,g=d(c);if(!(!g||c.getLine(g.from.line).length>f||g.to&&c.getLine(g.to.line).length>f)){var h=g.match?"CodeMirror-matchingbracket":"CodeMirror-nonmatchingbracket",i=c.markText(g.from,b(g.from.line,g.from.ch+1),{className:h}),j=g.to&&c.markText(g.to,b(g.to.line,g.to.ch+1),{className:h});a&&c.state.focused&&c.display.input.focus();var k=function(){c.operation(function(){i.clear(),j&&j.clear()})};return e?(setTimeout(k,800),void 0):k -}}function g(a){a.operation(function(){f&&(f(),f=null),a.somethingSelected()||(f=e(a,!1))})}var a=/MSIE \d/.test(navigator.userAgent)&&(null==document.documentMode||document.documentMode<8),b=CodeMirror.Pos,c={"(":")>",")":"(<","[":"]>","]":"[<","{":"}>","}":"{<"},f=null;CodeMirror.defineOption("matchBrackets",!1,function(a,b,c){c&&c!=CodeMirror.Init&&a.off("cursorActivity",g),b&&(a.state.matchBrackets="object"==typeof b?b:{},a.on("cursorActivity",g))}),CodeMirror.defineExtension("matchBrackets",function(){e(this,!0)}),CodeMirror.defineExtension("findMatchingBracket",function(a,b){return d(this,a,b)})}(),CodeMirror.runMode=function(a,b,c,d){var e=CodeMirror.getMode(CodeMirror.defaults,b),f=/MSIE \d/.test(navigator.userAgent),g=f&&(null==document.documentMode||document.documentMode<9);if(1==c.nodeType){var h=d&&d.tabSize||CodeMirror.defaults.tabSize,i=c,j=0;i.innerHTML="",c=function(a,b){if("\n"==a)return i.appendChild(document.createTextNode(g?"\r":a)),j=0,void 0;for(var c="",d=0;;){var e=a.indexOf(" ",d);if(-1==e){c+=a.slice(d),j+=a.length-d;break}j+=e-d,c+=a.slice(d,e);var f=h-j%h;j+=f;for(var k=0;f>k;++k)c+=" ";d=e+1}if(b){var l=i.appendChild(document.createElement("span"));l.className="cm-"+b.replace(/ +/g," cm-"),l.appendChild(document.createTextNode(c))}else i.appendChild(document.createTextNode(c))}}for(var k=CodeMirror.splitLines(a),l=d&&d.state||CodeMirror.startState(e),m=0,n=k.length;n>m;++m){m&&c("\n");for(var o=new CodeMirror.StringStream(k[m]);!o.eol();){var p=e.token(o,l);c(o.current(),p,m,o.start,l),o.start=o.pos}}}; \ No newline at end of file diff --git a/addon-sdk/source/examples/actor-repl/data/codemirror.css b/addon-sdk/source/examples/actor-repl/data/codemirror.css deleted file mode 100644 --- a/addon-sdk/source/examples/actor-repl/data/codemirror.css +++ /dev/null @@ -1,264 +0,0 @@ -/* BASICS */ - -.CodeMirror { - /* Set height, width, borders, and global font properties here */ - font-family: monospace; - height: 300px; -} -.CodeMirror-scroll { - /* Set scrolling behaviour here */ - overflow: auto; -} - -/* PADDING */ - -.CodeMirror-lines { - padding: 4px 0; /* Vertical padding around content */ -} -.CodeMirror pre { - padding: 0 4px; /* Horizontal padding of content */ -} - -.CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler { - background-color: white; /* The little square between H and V scrollbars */ -} - -/* GUTTER */ - -.CodeMirror-gutters { - border-right: 1px solid #ddd; - background-color: #f7f7f7; - white-space: nowrap; -} -.CodeMirror-linenumbers {} -.CodeMirror-linenumber { - padding: 0 3px 0 5px; - min-width: 20px; - text-align: right; - color: #999; - -moz-box-sizing: content-box; - box-sizing: content-box; -} - -/* CURSOR */ - -.CodeMirror div.CodeMirror-cursor { - border-left: 1px solid black; - z-index: 3; -} -/* Shown when moving in bi-directional text */ -.CodeMirror div.CodeMirror-secondarycursor { - border-left: 1px solid silver; -} -.CodeMirror.cm-keymap-fat-cursor div.CodeMirror-cursor { - width: auto; - border: 0; - background: #7e7; - z-index: 1; -} -/* Can style cursor different in overwrite (non-insert) mode */ -.CodeMirror div.CodeMirror-cursor.CodeMirror-overwrite {} - -.cm-tab { display: inline-block; } - -.CodeMirror-ruler { - border-left: 1px solid #ccc; - position: absolute; -} - -/* DEFAULT THEME */ - -.cm-s-default .cm-keyword {color: #708;} -.cm-s-default .cm-atom {color: #219;} -.cm-s-default .cm-number {color: #164;} -.cm-s-default .cm-def {color: #00f;} -.cm-s-default .cm-variable {color: black;} -.cm-s-default .cm-variable-2 {color: #05a;} -.cm-s-default .cm-variable-3 {color: #085;} -.cm-s-default .cm-property {color: black;} -.cm-s-default .cm-operator {color: black;} -.cm-s-default .cm-comment {color: #a50;} -.cm-s-default .cm-string {color: #a11;} -.cm-s-default .cm-string-2 {color: #f50;} -.cm-s-default .cm-meta {color: #555;} -.cm-s-default .cm-qualifier {color: #555;} -.cm-s-default .cm-builtin {color: #30a;} -.cm-s-default .cm-bracket {color: #997;} -.cm-s-default .cm-tag {color: #170;} -.cm-s-default .cm-attribute {color: #00c;} -.cm-s-default .cm-header {color: blue;} -.cm-s-default .cm-quote {color: #090;} -.cm-s-default .cm-hr {color: #999;} -.cm-s-default .cm-link {color: #00c;} - -.cm-negative {color: #d44;} -.cm-positive {color: #292;} -.cm-header, .cm-strong {font-weight: bold;} -.cm-em {font-style: italic;} -.cm-link {text-decoration: underline;} - -.cm-s-default .cm-error {color: #f00;} -.cm-invalidchar {color: #f00;} - -div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;} -div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;} -.CodeMirror-activeline-background {background: #e8f2ff;} - -/* STOP */ - -/* The rest of this file contains styles related to the mechanics of - the editor. You probably shouldn't touch them. */ - -.CodeMirror { - line-height: 1; - position: relative; - overflow: hidden; - background: white; - color: black; -} - -.CodeMirror-scroll { - /* 30px is the magic margin used to hide the element's real scrollbars */ - /* See overflow: hidden in .CodeMirror */ - margin-bottom: -30px; margin-right: -30px; - padding-bottom: 30px; - height: 100%; - outline: none; /* Prevent dragging from highlighting the element */ - position: relative; - -moz-box-sizing: content-box; - box-sizing: content-box; -} -.CodeMirror-sizer { - position: relative; - border-right: 30px solid transparent; - -moz-box-sizing: content-box; - box-sizing: content-box; -} - -/* The fake, visible scrollbars. Used to force redraw during scrolling - before actuall scrolling happens, thus preventing shaking and - flickering artifacts. */ -.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler { - position: absolute; - z-index: 6; - display: none; -} -.CodeMirror-vscrollbar { - right: 0; top: 0; - overflow-x: hidden; - overflow-y: scroll; -} -.CodeMirror-hscrollbar { - bottom: 0; left: 0; - overflow-y: hidden; - overflow-x: scroll; -} -.CodeMirror-scrollbar-filler { - right: 0; bottom: 0; -} -.CodeMirror-gutter-filler { - left: 0; bottom: 0; -} - -.CodeMirror-gutters { - position: absolute; left: 0; top: 0; - padding-bottom: 30px; - z-index: 3; -} -.CodeMirror-gutter { - white-space: normal; - height: 100%; - -moz-box-sizing: content-box; - box-sizing: content-box; - padding-bottom: 30px; - margin-bottom: -32px; - display: inline-block; - /* Hack to make IE7 behave */ - *zoom:1; - *display:inline; -} -.CodeMirror-gutter-elt { - position: absolute; - cursor: default; - z-index: 4; -} - -.CodeMirror-lines { - cursor: text; -} -.CodeMirror pre { - /* Reset some styles that the rest of the page might have set */ - -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0; - border-width: 0; - background: transparent; - font-family: inherit; - font-size: inherit; - margin: 0; - white-space: pre; - word-wrap: normal; - line-height: inherit; - color: inherit; - z-index: 2; - position: relative; - overflow: visible; -} -.CodeMirror-wrap pre { - word-wrap: break-word; - white-space: pre-wrap; - word-break: normal; -} - -.CodeMirror-linebackground { - position: absolute; - left: 0; right: 0; top: 0; bottom: 0; - z-index: 0; -} - -.CodeMirror-linewidget { - position: relative; - z-index: 2; - overflow: auto; -} - -.CodeMirror-widget {} - -.CodeMirror-wrap .CodeMirror-scroll { - overflow-x: hidden; -} - -.CodeMirror-measure { - position: absolute; - width: 100%; - height: 0; - overflow: hidden; - visibility: hidden; -} -.CodeMirror-measure pre { position: static; } - -.CodeMirror div.CodeMirror-cursor { - position: absolute; - visibility: hidden; - border-right: none; - width: 0; -} -.CodeMirror-focused div.CodeMirror-cursor { - visibility: visible; -} - -.CodeMirror-selected { background: #d9d9d9; } -.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; } - -.cm-searching { - background: #ffa; - background: rgba(255, 255, 0, .4); -} - -/* IE7 hack to prevent it from returning funny offsetTops on the spans */ -.CodeMirror span { *vertical-align: text-bottom; } - -@media print { - /* Hide the cursor when printing */ - .CodeMirror div.CodeMirror-cursor { - visibility: hidden; - } -} diff --git a/addon-sdk/source/examples/actor-repl/data/index.html b/addon-sdk/source/examples/actor-repl/data/index.html deleted file mode 100644 --- a/addon-sdk/source/examples/actor-repl/data/index.html +++ /dev/null @@ -1,147 +0,0 @@ - - - - - - - -
-

-            
-
-
- - -

-  
-  
-  
-
diff --git a/addon-sdk/source/examples/actor-repl/data/main.css b/addon-sdk/source/examples/actor-repl/data/main.css
deleted file mode 100644
--- a/addon-sdk/source/examples/actor-repl/data/main.css
+++ /dev/null
@@ -1,117 +0,0 @@
-/* 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/. */
-
-body
-{
-  position: absolute;
-  width: 100%;
-  margin: 0;
-  padding: 0;
-  background: white;
-}
-
-
-pre
-{
-  margin: 0;
-}
-
-section
-{
-  border-top: 1px solid rgba(150, 150, 150, 0.5);
-}
-
-.CodeMirror {
-  height: auto;
-}
-.CodeMirror-scroll {
-  overflow-y: hidden;
-  overflow-x: auto;
-}
-
-.request,
-.response,
-.input
-{
-  border-left: 5px solid;
-  padding-left: 10px;
-}
-
-.request:not(:empty),
-.response.pending
-{
-  padding: 5px;
-}
-
-.input
-{
-  padding-left: 6px;
-  border-color: lightgreen;
-}
-.input.invalid
-{
-  border-color: orange;
-}
-
-.request
-{
-  border-color: lightgrey;
-}
-
-.response
-{
-  border-color: grey;
-}
-.response.error
-{
-  border-color: red;
-}
-
-.response.message
-{
-    border-color: lightblue;
-}
-
-.response .one,
-.response .two,
-.response .three
-{
-  width: 0;
-  height: auto;
-}
-
-
-
-.response.pending .one,
-.response.pending .two,
-.response.pending .three
-{
-  width: 10px;
-  height: 10px;
-  background-color: rgba(150, 150, 150, 0.5);
-
-  border-radius: 100%;
-  display: inline-block;
-  animation: bouncedelay 1.4s infinite ease-in-out;
-  /* Prevent first frame from flickering when animation starts */
-  animation-fill-mode: both;
-}
-
-.response.pending .one
-{
-  animation-delay: -0.32s;
-}
-
-.response.pending .two
-{
-  animation-delay: -0.16s;
-}
-
-@keyframes bouncedelay {
-  0%, 80%, 100% {
-    transform: scale(0.0);
-  } 40% {
-    transform: scale(1.0);
-  }
-}
diff --git a/addon-sdk/source/examples/actor-repl/data/robot.png b/addon-sdk/source/examples/actor-repl/data/robot.png
deleted file mode 100644
index 983516f981f2e0c2110e27d0c42961a5a6bb3d1d..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@ {
-  var constructor = fields.constructor || function() {};
-  var ancestor = fields.extends || Object;
-
-
-
-  var descriptor = {};
-  for (var key of Object.keys(fields))
-    descriptor[key] = describe(fields, key);
-
-  var prototype = Object.create(ancestor.prototype, descriptor);
-
-  constructor.prototype = prototype;
-  prototype.constructor = constructor;
-
-  return constructor;
-};
-
-
-var bus = function Bus() {
-  var parser = new DOMParser();
-  return parser.parseFromString("", "application/xml").documentElement;
-}();
-
-var GUID = new WeakMap();
-GUID.id = 0;
-var guid = x => GUID.get(x);
-var setGUID = x => {
-  GUID.set(x, ++ GUID.id);
-};
-
-var Emitter = Class({
-  extends: EventTarget,
-  constructor: function() {
-   this.setupEmitter();
-  },
-  setupEmitter: function() {
-    setGUID(this);
-  },
-  addEventListener: function(type, listener, capture) {
-    bus.addEventListener(type + "@" + guid(this),
-                         listener, capture);
-  },
-  removeEventListener: function(type, listener, capture) {
-    bus.removeEventListener(type + "@" + guid(this),
-                            listener, capture);
-  }
-});
-
-function dispatch(target, type, data) {
-  var event = new MessageEvent(type + "@" + guid(target), {
-    bubbles: true,
-    cancelable: false,
-    data: data
-  });
-  bus.dispatchEvent(event);
-}
-
-var supervisedWorkers = new WeakMap();
-var supervised = supervisor => {
-  if (!supervisedWorkers.has(supervisor)) {
-    supervisedWorkers.set(supervisor, new Map());
-    supervisor.connection.addActorPool(supervisor);
-  }
-  return supervisedWorkers.get(supervisor);
-};
-
-var Supervisor = Class({
-  extends: Emitter,
-  constructor: function(...params) {
-    this.setupEmitter(...params);
-    this.setupSupervisor(...params);
-  },
-  Supervisor: function(connection) {
-    this.connection = connection;
-  },
-  /**
-   * Return the parent pool for this client.
-   */
-  supervisor: function() {
-    return this.connection.poolFor(this.actorID);
-  },
-  /**
-   * Override this if you want actors returned by this actor
-   * to belong to a different actor by default.
-   */
-  marshallPool: function() { return this; },
-    /**
-   * Add an actor as a child of this pool.
-   */
-  supervise: function(actor) {
-    if (!actor.actorID)
-      actor.actorID = this.connection.allocID(actor.actorPrefix ||
-                                              actor.typeName);
-
-    supervised(this).set(actor.actorID, actor);
-    return actor;
-  },
-  /**
-   * Remove an actor as a child of this pool.
-   */
-  abandon: function(actor) {
-    supervised(this).delete(actor.actorID);
-  },
-  // true if the given actor ID exists in the pool.
-  has: function(actorID) {
-    return supervised(this).has(actorID);
-  },
-  // Same as actor, should update debugger connection to use 'actor'
-  // and then remove this.
-  get: function(actorID) {
-    return supervised(this).get(actorID);
-  },
-  actor: function(actorID) {
-    return supervised(this).get(actorID);
-  },
-  isEmpty: function() {
-    return supervised(this).size === 0;
-  },
-  /**
-   * For getting along with the debugger server pools, should be removable
-   * eventually.
-   */
-  cleanup: function() {
-    this.destroy();
-  },
-  destroy: function() {
-    var supervisor = this.supervisor();
-    if (supervisor)
-      supervisor.abandon(this);
-
-    for (var actor of supervised(this).values()) {
-      if (actor !== this) {
-        var destroy = actor.destroy;
-        // Disconnect destroy while we're destroying in case of (misbehaving)
-        // circular ownership.
-        if (destroy) {
-          actor.destroy = null;
-          destroy.call(actor);
-          actor.destroy = destroy;
-        }
-      }
-    }
-
-    this.connection.removeActorPool(this);
-    supervised(this).clear();
-  }
-
-});
-
-
-
-
-var mailbox = new WeakMap();
-var clientRequests = new WeakMap();
-
-var inbox = client => mailbox.get(client).inbox;
-var outbox = client => mailbox.get(client).outbox;
-var requests = client => clientRequests.get(client);
-
-
-var Receiver = Class({
-  receive: function(packet) {
-    if (packet.error)
-      this.reject(packet.error);
-    else
-      this.resolve(this.read(packet));
-  }
-});
-
-var Connection = Class({
-  constructor: function() {
-    // Queue of the outgoing messages.
-    this.outbox = [];
-    // Map of pending requests.
-    this.pending = new Map();
-    this.pools = new Set();
-  },
-  isConnected: function() {
-    return !!this.port
-  },
-  connect: function(port) {
-    this.port = port;
-    port.addEventListener("message", this);
-    port.start();
-
-    this.flush();
-  },
-  addPool: function(pool) {
-    this.pools.add(pool);
-  },
-  removePool: function(pool) {
-    this.pools.delete(pool);
-  },
-  poolFor: function(id) {
-    for (let pool of this.pools.values()) {
-      if (pool.has(id))
-        return pool;
-    }
-  },
-  get: function(id) {
-    var pool = this.poolFor(id);
-    return pool && pool.get(id);
-  },
-  disconnect: function() {
-    this.port.stop();
-    this.port = null;
-    for (var request of this.pending.values()) {
-      request.catch(new Error("Connection closed"));
-    }
-    this.pending.clear();
-
-    var requests = this.outbox.splice(0);
-    for (var request of request) {
-      requests.catch(new Error("Connection closed"));
-    }
-  },
-  handleEvent: function(event) {
-    this.receive(event.data);
-  },
-  flush: function() {
-    if (this.isConnected()) {
-      for (var request of this.outbox) {
-        if (!this.pending.has(request.to)) {
-          this.outbox.splice(this.outbox.indexOf(request), 1);
-          this.pending.set(request.to, request);
-          this.send(request.packet);
-        }
-      }
-    }
-  },
-  send: function(packet) {
-    this.port.postMessage(packet);
-  },
-  request: function(packet) {
-    return new Promise(function(resolve, reject) {
-      this.outbox.push({
-        to: packet.to,
-        packet: packet,
-        receive: resolve,
-        catch: reject
-      });
-      this.flush();
-    });
-  },
-  receive: function(packet) {
-    var { from, type, why } = packet;
-    var receiver = this.pending.get(from);
-    if (!receiver) {
-      console.warn("Unable to handle received packet", data);
-    } else {
-      this.pending.delete(from);
-      if (packet.error)
-        receiver.catch(packet.error);
-      else
-        receiver.receive(packet);
-    }
-    this.flush();
-  },
-});
-
-/**
- * Base class for client-side actor fronts.
- */
-var Client = Class({
-  extends: Supervisor,
-  constructor: function(from=null, detail=null, connection=null) {
-    this.Client(from, detail, connection);
-  },
-  Client: function(form, detail, connection) {
-    this.Supervisor(connection);
-
-    if (form) {
-      this.actorID = form.actor;
-      this.from(form, detail);
-    }
-  },
-  connect: function(port) {
-    this.connection = new Connection(port);
-  },
-  actorID: null,
-  actor: function() {
-    return this.actorID;
-  },
-  /**
-   * Update the actor from its representation.
-   * Subclasses should override this.
-   */
-  form: function(form) {
-  },
-  /**
-   * Method is invokeid when packet received constitutes an
-   * event. By default such packets are demarshalled and
-   * dispatched on the client instance.
-   */
-  dispatch: function(packet) {
-  },
-  /**
-   * Method is invoked when packet is returned in response to
-   * a request. By default respond delivers response to a first
-   * request in a queue.
-   */
-  read: function(input) {
-    throw new TypeError("Subclass must implement read method");
-  },
-  write: function(input) {
-    throw new TypeError("Subclass must implement write method");
-  },
-  respond: function(packet) {
-    var [resolve, reject] = requests(this).shift();
-    if (packet.error)
-      reject(packet.error);
-    else
-      resolve(this.read(packet));
-  },
-  receive: function(packet) {
-    if (this.isEventPacket(packet)) {
-      this.dispatch(packet);
-    }
-    else if (requests(this).length) {
-      this.respond(packet);
-    }
-    else {
-      this.catch(packet);
-    }
-  },
-  send: function(packet) {
-    Promise.cast(packet.to || this.actor()).then(id => {
-      packet.to = id;
-      this.connection.send(packet);
-    })
-  },
-  request: function(packet) {
-    return this.connection.request(packet);
-  }
-});
-
-
-var Destructor = method => {
-  return function(...args) {
-    return method.apply(this, args).then(result => {
-      this.destroy();
-      return result;
-    });
-  };
-};
-
-var Profiled = (method, id) => {
-  return function(...args) {
-    var start = new Date();
-    return method.apply(this, args).then(result => {
-      var end = new Date();
-      this.telemetry.add(id, +end - start);
-      return result;
-    });
-  };
-};
-
-var Method = (request, response) => {
-  return response ? new BidirectionalMethod(request, response) :
-         new UnidirecationalMethod(request);
-};
-
-var UnidirecationalMethod = request => {
-  return function(...args) {
-    var packet = request.write(args, this);
-    this.connection.send(packet);
-    return Promise.resolve(void(0));
-  };
-};
-
-var BidirectionalMethod = (request, response) => {
-  return function(...args) {
-    var packet = request.write(args, this);
-    return this.connection.request(packet).then(packet => {
-      return response.read(packet, this);
-    });
-  };
-};
-
-
-Client.from = ({category, typeName, methods, events}) => {
-  var proto = {
-    constructor: function(...args) {
-      this.Client(...args);
-    },
-    extends: Client,
-    name: typeName
-  };
-
-  methods.forEach(({telemetry, request, response, name, oneway, release}) => {
-    var [reader, writer] = oneway ? [, new Request(request)] :
-                           [new Request(request), new Response(response)];
-    var method = new Method(request, response);
-    var profiler = telemetry ? new Profiler(method) : method;
-    var destructor = release ? new Destructor(profiler) : profiler;
-    proto[name] = destructor;
-  });
-
-  return Class(proto);
-};
-
-
-var defineType = (client, descriptor) => {
-  var type = void(0)
-  if (typeof(descriptor) === "string") {
-    if (name.indexOf(":") > 0)
-      type = makeCompoundType(descriptor);
-    else if (name.indexOf("#") > 0)
-      type = new ActorDetail(descriptor);
-    else if (client.specification[descriptor])
-      type = makeCategoryType(client.specification[descriptor]);
-  } else {
-    type = makeCategoryType(descriptor);
-  }
-
-  if (type)
-    client.types.set(type.name, type);
-  else
-    throw TypeError("Invalid type: " + descriptor);
-};
-
-
-var makeCompoundType = name => {
-  var index = name.indexOf(":");
-  var [baseType, subType] = [name.slice(0, index), parts.slice(1)];
-  return baseType === "array" ? new ArrayOf(subType) :
-         baseType === "nullable" ? new Maybe(subType) :
-         null;
-};
-
-var makeCategoryType = (descriptor) => {
-  var { category } = descriptor;
-  return category === "dict" ? new Dictionary(descriptor) :
-         category === "actor" ? new Actor(descriptor) :
-         null;
-};
-
-
-var typeFor = (client, type="primitive") => {
-  if (!client.types.has(type))
-    defineType(client, type);
-
-  return client.types.get(type);
-};
-
-
-var Client = Class({
-  constructor: function() {
-  },
-  setupTypes: function(specification) {
-    this.specification = specification;
-    this.types = new Map();
-  },
-  read: function(input, type) {
-    return typeFor(this, type).read(input, this);
-  },
-  write: function(input, type) {
-    return typeFor(this, type).write(input, this);
-  }
-});
-
-
-var Type = Class({
-  get name() {
-    return this.category ? this.category + ":" + this.type :
-           this.type;
-  },
-  read: function(input, client) {
-    throw new TypeError("`Type` subclass must implement `read`");
-  },
-  write: function(input, client) {
-    throw new TypeError("`Type` subclass must implement `write`");
-  }
-});
-
-
-var Primitve = Class({
-  extends: Type,
-  constuctor: function(type) {
-    this.type = type;
-  },
-  read: function(input, client) {
-    return input;
-  },
-  write: function(input, client) {
-    return input;
-  }
-});
-
-var Maybe = Class({
-  extends: Type,
-  category: "nullable",
-  constructor: function(type) {
-    this.type = type;
-  },
-  read: function(input, client) {
-    return input === null ? null :
-           input === void(0) ? void(0) :
-           client.read(input, this.type);
-  },
-  write: function(input, client) {
-    return input === null ? null :
-           input === void(0) ? void(0) :
-           client.write(input, this.type);
-  }
-});
-
-var ArrayOf = Class({
-  extends: Type,
-  category: "array",
-  constructor: function(type) {
-    this.type = type;
-  },
-  read: function(input, client) {
-    return input.map($ => client.read($, this.type));
-  },
-  write: function(input, client) {
-    return input.map($ => client.write($, this.type));
-  }
-});
-
-var Dictionary = Class({
-  exteds: Type,
-  category: "dict",
-  get name() { return this.type; },
-  constructor: function({typeName, specializations}) {
-    this.type = typeName;
-    this.types = specifications;
-  },
-  read: function(input, client) {
-    var output = {};
-    for (var key in input) {
-      output[key] = client.read(input[key], this.types[key]);
-    }
-    return output;
-  },
-  write: function(input, client) {
-    var output = {};
-    for (var key in input) {
-      output[key] = client.write(value, this.types[key]);
-    }
-    return output;
-  }
-});
-
-var Actor = Class({
-  exteds: Type,
-  category: "actor",
-  get name() { return this.type; },
-  constructor: function({typeName}) {
-    this.type = typeName;
-  },
-  read: function(input, client, detail) {
-    var id = value.actor;
-    var actor = void(0);
-    if (client.connection.has(id)) {
-      return client.connection.get(id).form(input, detail, client);
-    } else {
-      actor = Client.from(detail, client);
-      actor.actorID = id;
-      client.supervise(actor);
-    }
-  },
-  write: function(input, client, detail) {
-    if (input instanceof Actor) {
-      if (!input.actorID) {
-        client.supervise(input);
-      }
-      return input.from(detail);
-    }
-    return input.actorID;
-  }
-});
-
-var Root = Client.from({
-  "category": "actor",
-  "typeName": "root",
-  "methods": [
-    {"name": "listTabs",
-     "request": {},
-     "response": {
-     }
-    },
-    {"name": "listAddons"
-    },
-    {"name": "echo",
-
-    },
-    {"name": "protocolDescription",
-
-    }
-  ]
-});
-
-
-var ActorDetail = Class({
-  extends: Actor,
-  constructor: function(name, actor, detail) {
-    this.detail = detail;
-    this.actor = actor;
-  },
-  read: function(input, client) {
-    this.actor.read(input, client, this.detail);
-  },
-  write: function(input, client) {
-    this.actor.write(input, client, this.detail);
-  }
-});
-
-var registeredLifetimes = new Map();
-var LifeTime = Class({
-  extends: Type,
-  category: "lifetime",
-  constructor: function(lifetime, type) {
-    this.name = lifetime + ":" + type.name;
-    this.field = registeredLifetimes.get(lifetime);
-  },
-  read: function(input, client) {
-    return this.type.read(input, client[this.field]);
-  },
-  write: function(input, client) {
-    return this.type.write(input, client[this.field]);
-  }
-});
-
-var primitive = new Primitve("primitive");
-var string = new Primitve("string");
-var number = new Primitve("number");
-var boolean = new Primitve("boolean");
-var json = new Primitve("json");
-var array = new Primitve("array");
-
-
-var TypedValue = Class({
-  extends: Type,
-  constructor: function(name, type) {
-    this.TypedValue(name, type);
-  },
-  TypedValue: function(name, type) {
-    this.name = name;
-    this.type = type;
-  },
-  read: function(input, client) {
-    return this.client.read(input, this.type);
-  },
-  write: function(input, client) {
-    return this.client.write(input, this.type);
-  }
-});
-
-var Return = Class({
-  extends: TypedValue,
-  constructor: function(type) {
-    this.type = type
-  }
-});
-
-var Argument = Class({
-  extends: TypedValue,
-  constructor: function(...args) {
-    this.Argument(...args);
-  },
-  Argument: function(index, type) {
-    this.index = index;
-    this.TypedValue("argument[" + index + "]", type);
-  },
-  read: function(input, client, target) {
-    return target[this.index] = client.read(input, this.type);
-  }
-});
-
-var Option = Class({
-  extends: Argument,
-  constructor: function(...args) {
-    return this.Argument(...args);
-  },
-  read: function(input, client, target, name) {
-    var param = target[this.index] || (target[this.index] = {});
-    param[name] = input === void(0) ? input : client.read(input, this.type);
-  },
-  write: function(input, client, name) {
-    var value = input && input[name];
-    return value === void(0) ? value : client.write(value, this.type);
-  }
-});
-
-var Request = Class({
-  extends: Type,
-  constructor: function(template={}) {
-    this.type = template.type;
-    this.template = template;
-    this.params = findPlaceholders(template, Argument);
-  },
-  read: function(packet, client) {
-    var args = [];
-    for (var param of this.params) {
-      var {placeholder, path} = param;
-      var name = path[path.length - 1];
-      placeholder.read(getPath(packet, path), client, args, name);
-      // TODO:
-      // args[placeholder.index] = placeholder.read(query(packet, path), client);
-    }
-    return args;
-  },
-  write: function(input, client) {
-    return JSON.parse(JSON.stringify(this.template, (key, value) => {
-      return value instanceof Argument ? value.write(input[value.index],
-                                                     client, key) :
-             value;
-    }));
-  }
-});
-
-var Response = Class({
-  extends: Type,
-  constructor: function(template={}) {
-    this.template = template;
-    var [x] = findPlaceholders(template, Return);
-    var {placeholder, path} = x;
-    this.return = placeholder;
-    this.path = path;
-  },
-  read: function(packet, client) {
-    var value = query(packet, this.path);
-    return this.return.read(value, client);
-  },
-  write: function(input, client) {
-    return JSON.parse(JSON.stringify(this.template, (key, value) => {
-      return value instanceof Return ? value.write(input) :
-             input
-    }));
-  }
-});
-
-// Returns array of values for the given object.
-var values = object => Object.keys(object).map(key => object[key]);
-// Returns [key, value] pairs for the given object.
-var pairs = object => Object.keys(object).map(key => [key, object[key]]);
-// Queries an object for the field nested with in it.
-var query = (object, path) => path.reduce((object, entry) => object && object[entry],
-                                          object);
-
-
-var Root = Client.from({
-  "category": "actor",
-  "typeName": "root",
-  "methods": [
-    {
-      "name": "echo",
-      "request": {
-        "string": { "_arg": 0, "type": "string" }
-      },
-      "response": {
-        "string": { "_retval": "string" }
-      }
-    },
-    {
-      "name": "listTabs",
-      "request": {},
-      "response": { "_retval": "tablist" }
-    },
-    {
-      "name": "actorDescriptions",
-      "request": {},
-      "response": { "_retval": "json" }
-    }
-  ],
-  "events": {
-    "tabListChanged": {}
-  }
-});
-
-var Tab = Client.from({
-  "category": "dict",
-  "typeName": "tab",
-  "specifications": {
-    "title": "string",
-    "url": "string",
-    "outerWindowID": "number",
-    "console": "console",
-    "inspectorActor": "inspector",
-    "callWatcherActor": "call-watcher",
-    "canvasActor": "canvas",
-    "webglActor": "webgl",
-    "webaudioActor": "webaudio",
-    "styleSheetsActor": "stylesheets",
-    "styleEditorActor": "styleeditor",
-    "storageActor": "storage",
-    "gcliActor": "gcli",
-    "memoryActor": "memory",
-    "eventLoopLag": "eventLoopLag",
-
-    "trace": "trace", // missing
-  }
-});
-
-var tablist = Client.from({
-  "category": "dict",
-  "typeName": "tablist",
-  "specializations": {
-    "selected": "number",
-    "tabs": "array:tab"
-  }
-});
-
-})(this);
-
diff --git a/addon-sdk/source/examples/debug-client/data/index.html b/addon-sdk/source/examples/debug-client/data/index.html
deleted file mode 100644
--- a/addon-sdk/source/examples/debug-client/data/index.html
+++ /dev/null
@@ -1,50 +0,0 @@
-
-
-  
-      
-      
-  
-  
-  
-  
-
diff --git a/addon-sdk/source/examples/debug-client/data/plugin.png b/addon-sdk/source/examples/debug-client/data/plugin.png
deleted file mode 100644
index 6a364a30a852c1cd9f54feba54220ef5605c1bb3..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@ {
-  return new Promise((resolve, reject) => {
-    try {
-      const routine = task(...args);
-      const raise = error => routine.throw(error);
-      const step = data => {
-        const { done, value } = routine.next(data);
-        if (done)
-          resolve(value);
-        else
-          Promise.resolve(value).then(step, raise);
-      }
-      step();
-    } catch(error) {
-      reject(error);
-    }
-  });
-}
-exports.spawn = spawn;
-
-})(Task = {});
diff --git a/addon-sdk/source/examples/debug-client/index.js b/addon-sdk/source/examples/debug-client/index.js
deleted file mode 100644
--- a/addon-sdk/source/examples/debug-client/index.js
+++ /dev/null
@@ -1,33 +0,0 @@
-/* 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/. */
-"use strict";
-
-const { Panel } = require("dev/panel");
-const { Tool } = require("dev/toolbox");
-const { Class } = require("sdk/core/heritage");
-
-
-const LadybugPanel = Class({
-  extends: Panel,
-  label: "Ladybug",
-  tooltip: "Debug client example",
-  icon: "./plugin.png",
-  url: "./index.html",
-  setup: function({debuggee}) {
-    this.debuggee = debuggee;
-  },
-  dispose: function() {
-    delete this.debuggee;
-  },
-  onReady: function() {
-    this.debuggee.start();
-    this.postMessage("RDP", [this.debuggee]);
-  },
-});
-exports.LadybugPanel = LadybugPanel;
-
-
-const ladybug = new Tool({
-  panels: { ladybug: LadybugPanel }
-});
diff --git a/addon-sdk/source/examples/debug-client/package.json b/addon-sdk/source/examples/debug-client/package.json
deleted file mode 100644
--- a/addon-sdk/source/examples/debug-client/package.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-  "name": "debug-client",
-  "id": "@debug-client",
-  "title": "Debug client",
-  "description": "Example debug client",
-  "version": "0.0.1",
-  "author": "Irakli Gozalishvili",
-  "main": "./index.js",
-  "license": "MPL-2.0"
-}
diff --git a/addon-sdk/source/examples/debug-client/test/test-main.js b/addon-sdk/source/examples/debug-client/test/test-main.js
deleted file mode 100644
--- a/addon-sdk/source/examples/debug-client/test/test-main.js
+++ /dev/null
@@ -1,10 +0,0 @@
-/* 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/. */
- "use strict";
-
-exports.testMain = function(assert) {
-  assert.pass("TODO: Write some tests.");
-};
-
-require("sdk/test").run(exports);
diff --git a/addon-sdk/source/examples/reading-data/data/mom.png b/addon-sdk/source/examples/reading-data/data/mom.png
deleted file mode 100644
index 4ba89a2c1ef900e9363746d45820f0b9e857e51f..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@
-
-
-

Hello World

- diff --git a/addon-sdk/source/examples/reading-data/lib/main.js b/addon-sdk/source/examples/reading-data/lib/main.js deleted file mode 100644 --- a/addon-sdk/source/examples/reading-data/lib/main.js +++ /dev/null @@ -1,53 +0,0 @@ -/* 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/. */ -"use strict"; - -var self = require("sdk/self"); -var { Panel } = require("sdk/panel"); -var { ToggleButton } = require("sdk/ui"); - -function replaceMom(html) { - return html.replace("World", "Mom"); -} -exports.replaceMom = replaceMom; - -exports.main = function(options, callbacks) { - console.log("My ID is " + self.id); - - // Load the sample HTML into a string. - var helloHTML = self.data.load("sample.html"); - - // Let's now modify it... - helloHTML = replaceMom(helloHTML); - - // ... and then create a panel that displays it. - var myPanel = Panel({ - contentURL: "data:text/html," + helloHTML, - onHide: handleHide - }); - - // Create a widget that displays the image. We'll attach the panel to it. - // When you click the widget, the panel will pop up. - var button = ToggleButton({ - id: "test-widget", - label: "Mom", - icon: './mom.png', - onChange: handleChange - }); - - // If you run cfx with --static-args='{"quitWhenDone":true}' this program - // will automatically quit Firefox when it's done. - if (options.staticArgs.quitWhenDone) - callbacks.quit(); -} - -function handleChange(state) { - if (state.checked) { - myPanel.show({ position: button }); - } -} - -function handleHide() { - button.state('window', { checked: false }); -} diff --git a/addon-sdk/source/examples/reading-data/package.json b/addon-sdk/source/examples/reading-data/package.json deleted file mode 100644 --- a/addon-sdk/source/examples/reading-data/package.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "reading-data", - "description": "A demonstration of reading bundled data.", - "keywords": [], - "author": "Brian Warner", - "contributors": [], - "license": "MPL-2.0", - "id": "reading-data-example@jetpack.mozillalabs.com" -} diff --git a/addon-sdk/source/examples/reading-data/tests/test-main.js b/addon-sdk/source/examples/reading-data/tests/test-main.js deleted file mode 100644 --- a/addon-sdk/source/examples/reading-data/tests/test-main.js +++ /dev/null @@ -1,25 +0,0 @@ -/* 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/. */ -"use strict"; - -var m = require("main"); -var self = require("sdk/self"); - -exports.testReplace = function(test) { - var input = "Hello World"; - var output = m.replaceMom(input); - test.assertEqual(output, "Hello Mom"); - var callbacks = { quit: function() {} }; - - // Make sure it doesn't crash... - m.main({ staticArgs: {} }, callbacks); -}; - -exports.testID = function(test) { - // The ID is randomly generated during tests, so we cannot compare it against - // anything in particular. Just assert that it is not empty. - test.assert(self.id.length > 0); - test.assertEqual(self.data.url("sample.html"), - "resource://reading-data-example-at-jetpack-dot-mozillalabs-dot-com/reading-data/data/sample.html"); -}; diff --git a/addon-sdk/source/examples/theme/data/icon-16.png b/addon-sdk/source/examples/theme/data/icon-16.png deleted file mode 100644 index 72327f77b67a4ede4fa787f67c5a810c077195b7..0000000000000000000000000000000000000000 GIT binary patch literal 0 Hc$@ - - - - - - diff --git a/addon-sdk/source/examples/theme/data/theme.css b/addon-sdk/source/examples/theme/data/theme.css deleted file mode 100644 --- a/addon-sdk/source/examples/theme/data/theme.css +++ /dev/null @@ -1,7 +0,0 @@ -/* 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/. */ - -#devtools-theme-box { - background-color: red !important; -} diff --git a/addon-sdk/source/examples/theme/lib/main.js b/addon-sdk/source/examples/theme/lib/main.js deleted file mode 100644 --- a/addon-sdk/source/examples/theme/lib/main.js +++ /dev/null @@ -1,37 +0,0 @@ -/* 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/. */ -"use strict"; - -const { Tool } = require("dev/toolbox"); -const { Class } = require("sdk/core/heritage"); -const { onEnable, onDisable } = require("dev/theme/hooks"); -const { Theme, LightTheme } = require("dev/theme"); - -/** - * This object represents a new theme registered within the Toolbox. - * You can activate it by clicking on "My Light Theme" theme option - * in the Options panel. - * Note that the new theme derives styles from built-in Light theme. - */ -const MyTheme = Theme({ - name: "mytheme", - label: "My Light Theme", - styles: [LightTheme, "./theme.css"], - - onEnable: function(window, oldTheme) { - console.log("myTheme.onEnable; method override " + - window.location.href); - }, - onDisable: function(window, newTheme) { - console.log("myTheme.onDisable; method override " + - window.location.href); - }, -}); - -// Registration - -const mytheme = new Tool({ - name: "My Tool", - themes: { mytheme: MyTheme } -}); diff --git a/addon-sdk/source/examples/theme/package.json b/addon-sdk/source/examples/theme/package.json deleted file mode 100644 --- a/addon-sdk/source/examples/theme/package.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "name": "theme", - "title": "theme", - "id": "theme@jetpack", - "description": "How to create new theme for devtools", - "author": "Jan Odvarko", - "license": "MPL-2.0", - "version": "0.1.0", - "main": "lib/main" -} diff --git a/addon-sdk/source/examples/theme/test/test-main.js b/addon-sdk/source/examples/theme/test/test-main.js deleted file mode 100644 --- a/addon-sdk/source/examples/theme/test/test-main.js +++ /dev/null @@ -1,10 +0,0 @@ -/* 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/. */ - "use strict"; - -exports.testMain = function(assert) { - assert.pass("TODO: Write some tests."); -}; - -require("sdk/test").run(exports); diff --git a/addon-sdk/source/examples/toolbar-api/data/favicon.ico b/addon-sdk/source/examples/toolbar-api/data/favicon.ico deleted file mode 100644 index ae5084bc03888f4e21da00633b349507248780ac..0000000000000000000000000000000000000000 GIT binary patch literal 0 Hc$@ - - - - - - - diff --git a/addon-sdk/source/examples/toolbar-api/lib/main.js b/addon-sdk/source/examples/toolbar-api/lib/main.js deleted file mode 100644 --- a/addon-sdk/source/examples/toolbar-api/lib/main.js +++ /dev/null @@ -1,48 +0,0 @@ -/* 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/. */ -"use strict"; - -const { Toolbar } = require("sdk/ui/toolbar"); -const { Frame } = require("sdk/ui/frame"); -const { ActionButton } = require("sdk/ui/button/action"); - -var button = new ActionButton({ - id: "button", - label: "send!", - icon: "./favicon.ico", - onClick: () => { - frame.postMessage({ - hello: "content" - }); - } -}); - -var frame = new Frame({ - url: "./index.html", - onAttach: () => { - console.log("frame was attached"); - }, - onReady: () => { - console.log("frame document was loaded"); - }, - onLoad: () => { - console.log("frame load complete"); - }, - onMessage: (event) => { - console.log("got message from frame content", event); - if (event.data === "ping!") - event.source.postMessage("pong!", event.source.origin); - } -}); -var toolbar = new Toolbar({ - items: [frame], - title: "Addon Demo", - hidden: false, - onShow: () => { - console.log("toolbar was shown"); - }, - onHide: () => { - console.log("toolbar was hidden"); - } -}); diff --git a/addon-sdk/source/examples/toolbar-api/package.json b/addon-sdk/source/examples/toolbar-api/package.json deleted file mode 100644 --- a/addon-sdk/source/examples/toolbar-api/package.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "name": "toolbar-api", - "title": "Toolbar API", - "main": "./lib/main.js", - "description": "a toolbar api example", - "author": "", - "license": "MPL-2.0", - "version": "0.1.1", - "engines": { - "firefox": ">=27.0 <=30.0" - } -} diff --git a/addon-sdk/source/examples/toolbar-api/test/test-main.js b/addon-sdk/source/examples/toolbar-api/test/test-main.js deleted file mode 100644 --- a/addon-sdk/source/examples/toolbar-api/test/test-main.js +++ /dev/null @@ -1,10 +0,0 @@ -/* 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/. */ - "use strict"; - -exports.testMain = function(assert) { - assert.pass("TODO: Write some tests."); -}; - -require("sdk/test").run(exports); diff --git a/addon-sdk/source/examples/ui-button-apis/lib/main.js b/addon-sdk/source/examples/ui-button-apis/lib/main.js deleted file mode 100644 --- a/addon-sdk/source/examples/ui-button-apis/lib/main.js +++ /dev/null @@ -1,39 +0,0 @@ -/* 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/. */ -"use strict"; - -var data = require('sdk/self').data; -var tabs = require('sdk/tabs'); -var { notify } = require('sdk/notifications'); -var { ActionButton, ToggleButton } = require('sdk/ui'); - -var icon = 'chrome://mozapps/skin/extensions/extensionGeneric.svg'; -exports.icon = icon; - -// your basic action button -var action = ActionButton({ - id: 'test-action-button', - label: 'Action Button', - icon: icon, - onClick: function (state) { - notify({ - title: "Action!", - text: "This notification was triggered from an action button!", - }); - } -}); -exports.actionButton = action; - -var toggle = ToggleButton({ - id: 'test-toggle-button', - label: 'Toggle Button', - icon: icon, - onClick: function (state) { - notify({ - title: "Toggled!", - text: "The current state of the button is " + state.checked, - }); - } -}); -exports.toggleButton = toggle; diff --git a/addon-sdk/source/examples/ui-button-apis/package.json b/addon-sdk/source/examples/ui-button-apis/package.json deleted file mode 100644 --- a/addon-sdk/source/examples/ui-button-apis/package.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "name": "ui-button-apis", - "title": "Australis Button API Examples", - "id": "ui-button-apis@mozilla.org", - "description": "A Button API example", - "author": "jeff@canuckistani.ca (Jeff Griffiths | @canuckistani)", - "license": "MPL-2.0", - "version": "0.1.1", - "main": "./lib/main.js" -} diff --git a/addon-sdk/source/examples/ui-button-apis/tests/test-main.js b/addon-sdk/source/examples/ui-button-apis/tests/test-main.js deleted file mode 100644 --- a/addon-sdk/source/examples/ui-button-apis/tests/test-main.js +++ /dev/null @@ -1,29 +0,0 @@ -/* 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/. */ -"use strict"; - -try { - // CFX use case.. - var { actionButton, toggleButton, icon } = require("main"); -} -catch (e) { - // JPM use case.. - let mainURI = "../lib/main"; - var { actionButton, toggleButton, icon } = require(mainURI); -} -var self = require("sdk/self"); - -exports.testActionButton = function(assert) { - assert.equal(actionButton.id, "test-action-button", "action button id is correct"); - assert.equal(actionButton.label, "Action Button", "action button label is correct"); - assert.equal(actionButton.icon, icon, "action button icon is correct"); -} - -exports.testToggleButton = function(assert) { - assert.equal(toggleButton.id, "test-toggle-button", "toggle button id is correct"); - assert.equal(toggleButton.label, "Toggle Button", "toggle button label is correct"); - assert.equal(toggleButton.icon, icon, "toggle button icon is correct"); -} - -require("sdk/test").run(exports); diff --git a/addon-sdk/source/gulpfile.js b/addon-sdk/source/gulpfile.js deleted file mode 100644 --- a/addon-sdk/source/gulpfile.js +++ /dev/null @@ -1,9 +0,0 @@ -/* 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/. */ -"use strict"; - -var gulp = require('gulp'); -var patch = require("./bin/node-scripts/apply-patch"); -var ini = require("./bin/node-scripts/update-ini"); - diff --git a/addon-sdk/source/mapping.json b/addon-sdk/source/mapping.json deleted file mode 100644 --- a/addon-sdk/source/mapping.json +++ /dev/null @@ -1,71 +0,0 @@ -{ - "api-utils": "sdk/deprecated/api-utils", - "base64": "sdk/base64", - "content": "sdk/content/content", - "deprecate": "sdk/util/deprecate", - "event/core": "sdk/event/core", - "events": "sdk/deprecated/events", - "functional": "sdk/core/functional", - "l10n/core": "sdk/l10n/json/core", - "l10n/html": "sdk/l10n/html", - "l10n/loader": "sdk/l10n/loader", - "l10n/locale": "sdk/l10n/locale", - "l10n/prefs": "sdk/l10n/prefs", - "list": "sdk/util/list", - "loader": "sdk/loader/loader", - "namespace": "sdk/core/namespace", - "preferences-service": "sdk/preferences/service", - "promise": "sdk/core/promise", - "system": "sdk/system", - "system/events": "sdk/system/events-shimmed", - "tabs/tab": "sdk/tabs/tab", - "tabs/utils": "sdk/tabs/utils", - "timer": "sdk/timers", - "traits": "sdk/deprecated/traits", - "unload": "sdk/system/unload", - "window-utils": "sdk/deprecated/window-utils", - "window/utils": "sdk/window/utils", - "windows/dom": "sdk/windows/dom", - "windows/loader": "sdk/windows/loader", - "xul-app": "sdk/system/xul-app", - "url": "sdk/url", - "traceback": "sdk/console/traceback", - "xhr": "sdk/net/xhr", - "match-pattern": "sdk/util/match-pattern", - "file": "sdk/io/file", - "runtime": "sdk/system/runtime", - "xpcom": "sdk/platform/xpcom", - "querystring": "sdk/querystring", - "text-streams": "sdk/io/text-streams", - "app-strings": "sdk/deprecated/app-strings", - "environment": "sdk/system/environment", - "keyboard/utils": "sdk/keyboard/utils", - "dom/events": "sdk/dom/events-shimmed", - "utils/data": "sdk/io/data", - "test/assert": "sdk/test/assert", - "hidden-frame": "sdk/frame/hidden-frame", - "collection": "sdk/util/collection", - "array": "sdk/util/array", - "clipboard": "sdk/clipboard", - "context-menu": "sdk/context-menu", - "hotkeys": "sdk/hotkeys", - "indexed-db": "sdk/indexed-db", - "l10n": "sdk/l10n", - "notifications": "sdk/notifications", - "page-mod": "sdk/page-mod", - "page-worker": "sdk/page-worker", - "panel": "sdk/panel", - "passwords": "sdk/passwords", - "private-browsing": "sdk/private-browsing", - "request": "sdk/request", - "selection": "sdk/selection", - "self": "sdk/self", - "simple-prefs": "sdk/simple-prefs", - "simple-storage": "sdk/simple-storage", - "tabs": "sdk/tabs", - "timers": "sdk/timers", - "windows": "sdk/windows", - "harness": "sdk/test/harness", - "run-tests": "sdk/test/runner", - "test": "sdk/test" -} diff --git a/addon-sdk/source/modules/system/moz.build b/addon-sdk/source/modules/system/moz.build deleted file mode 100644 --- a/addon-sdk/source/modules/system/moz.build +++ /dev/null @@ -1,9 +0,0 @@ -# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- -# vim: set filetype=python: -# 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/. - -EXTRA_JS_MODULES.sdk.system += [ - 'Startup.js', -] diff --git a/addon-sdk/source/package.json b/addon-sdk/source/package.json deleted file mode 100644 --- a/addon-sdk/source/package.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "name": "addon-sdk", - "description": "Add-on development made easy.", - "keywords": [ - "javascript", "engine", "addon", "extension", - "xulrunner", "firefox", "browser" - ], - "license": "MPL-2.0", - "unpack": true, - "scripts": { - "test": "gulp test" - }, - "homepage": "https://github.com/mozilla/addon-sdk", - "repository": { - "type": "git", - "url": "git://github.com/mozilla/addon-sdk.git" - }, - "version": "0.1.18", - "main": "./lib/index.js", - "loader": "lib/sdk/loader/cuddlefish.js", - "devDependencies": { - "async": "0.9.0", - "chai": "2.1.1", - "fs-extra": "0.18.2", - "fx-runner": "0.0.7", - "glob": "4.4.2", - "gulp": "3.8.11", - "ini-parser": "0.0.2", - "jpm": "0.0.29", - "lodash": "3.3.1", - "mocha": "2.1.0", - "patch-editor": "0.0.1", - "promise": "6.1.0", - "rimraf": "2.3.1", - "teacher": "0.0.1", - "unzip": "0.1.11", - "xmldom": "0.1.19" - } -} diff --git a/addon-sdk/source/python-lib/cuddlefish/__init__.py b/addon-sdk/source/python-lib/cuddlefish/__init__.py deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/__init__.py +++ /dev/null @@ -1,959 +0,0 @@ -# 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/. - -import sys -import os -import optparse -import time - -from copy import copy -import simplejson as json -from cuddlefish import packaging -from cuddlefish._version import get_versions - -MOZRUNNER_BIN_NOT_FOUND = 'Mozrunner could not locate your binary' -MOZRUNNER_BIN_NOT_FOUND_HELP = """ -I can't find the application binary in any of its default locations -on your system. Please specify one using the -b/--binary option. -""" - -UPDATE_RDF_FILENAME = "%s.update.rdf" -XPI_FILENAME = "%s.xpi" - -usage = """ -%prog [options] command [command-specific options] - -Supported Commands: - init - create a sample addon in an empty directory - test - run tests - run - run program - xpi - generate an xpi - -Internal Commands: - testcfx - test the cfx tool - testex - test all example code - testpkgs - test all installed packages - testall - test whole environment - -Experimental and internal commands and options are not supported and may be -changed or removed in the future. -""" - -global_options = [ - (("-v", "--verbose",), dict(dest="verbose", - help="enable lots of output", - action="store_true", - default=False)), - ] - -parser_groups = ( - ("Supported Command-Specific Options", [ - (("", "--update-url",), dict(dest="update_url", - help="update URL in install.rdf", - metavar=None, - default=None, - cmds=['xpi'])), - (("", "--update-link",), dict(dest="update_link", - help="generate update.rdf", - metavar=None, - default=None, - cmds=['xpi'])), - (("-p", "--profiledir",), dict(dest="profiledir", - help=("profile directory to pass to " - "app"), - metavar=None, - default=None, - cmds=['test', 'run', 'testex', - 'testpkgs', 'testall'])), - (("-b", "--binary",), dict(dest="binary", - help="path to app binary", - metavar=None, - default=None, - cmds=['test', 'run', 'testex', 'testpkgs', - 'testall'])), - (("", "--binary-args",), dict(dest="cmdargs", - help=("additional arguments passed to the " - "binary"), - metavar=None, - default=None, - cmds=['run', 'test'])), - (("", "--dependencies",), dict(dest="dep_tests", - help="include tests for all deps", - action="store_true", - default=False, - cmds=['test', 'testex', 'testpkgs', - 'testall'])), - (("", "--times",), dict(dest="iterations", - type="int", - help="number of times to run tests", - default=1, - cmds=['test', 'testex', 'testpkgs', - 'testall'])), - (("-f", "--filter",), dict(dest="filter", - help=("only run tests whose filenames " - "match FILENAME and optionally " - "match TESTNAME, both regexps"), - metavar="FILENAME[:TESTNAME]", - default='', - cmds=['test', 'testex', 'testaddons', 'testpkgs', - 'testall'])), - (("-g", "--use-config",), dict(dest="config", - help="use named config from local.json", - metavar=None, - default="default", - cmds=['test', 'run', 'xpi', 'testex', - 'testpkgs', 'testall'])), - (("", "--templatedir",), dict(dest="templatedir", - help="XULRunner app/ext. template", - metavar=None, - default=None, - cmds=['run', 'xpi'])), - (("", "--package-path",), dict(dest="packagepath", action="append", - help="extra directories for package search", - metavar=None, - default=[], - cmds=['run', 'xpi', 'test'])), - (("", "--extra-packages",), dict(dest="extra_packages", - help=("extra packages to include, " - "comma-separated. Default is " - "'addon-sdk'."), - metavar=None, - default="addon-sdk", - cmds=['run', 'xpi', 'test', 'testex', - 'testpkgs', 'testall', - 'testcfx'])), - (("", "--pkgdir",), dict(dest="pkgdir", - help=("package dir containing " - "package.json; default is " - "current directory"), - metavar=None, - default=None, - cmds=['run', 'xpi', 'test'])), - (("", "--static-args",), dict(dest="static_args", - help="extra harness options as JSON", - type="json", - metavar=None, - default="{}", - cmds=['run', 'xpi'])), - (("", "--parseable",), dict(dest="parseable", - help="display test output in a parseable format", - action="store_true", - default=False, - cmds=['run', 'test', 'testex', 'testpkgs', - 'testaddons', 'testall'])), - ] - ), - - ("Experimental Command-Specific Options", [ - (("-a", "--app",), dict(dest="app", - help=("app to run: firefox (default), fennec, " - "fennec-on-device, xulrunner or " - "thunderbird"), - metavar=None, - type="choice", - choices=["firefox", - "fennec-on-device", "thunderbird", - "xulrunner"], - default="firefox", - cmds=['test', 'run', 'testex', 'testpkgs', - 'testall'])), - (("-o", "--overload-modules",), dict(dest="overload_modules", - help=("Overload JS modules integrated into" - " Firefox with the one from your SDK" - " repository"), - action="store_true", - default=False, - cmds=['run', 'test', 'testex', 'testpkgs', - 'testall'])), - (("", "--strip-sdk",), dict(dest="bundle_sdk", - help=("Do not ship SDK modules in the xpi"), - action="store_false", - default=False, - cmds=['run', 'test', 'testex', 'testpkgs', - 'testall', 'xpi'])), - (("", "--force-use-bundled-sdk",), dict(dest="force_use_bundled_sdk", - help=("When --strip-sdk isn't passed, " - "force using sdk modules shipped in " - "the xpi instead of firefox ones"), - action="store_true", - default=False, - cmds=['run', 'test', 'testex', 'testpkgs', - 'testall', 'xpi'])), - (("", "--no-run",), dict(dest="no_run", - help=("Instead of launching the " - "application, just show the command " - "for doing so. Use this to launch " - "the application in a debugger like " - "gdb."), - action="store_true", - default=False, - cmds=['run', 'test'])), - (("", "--no-quit",), dict(dest="no_quit", - help=("Prevent from killing Firefox when" - "running tests"), - action="store_true", - default=False, - cmds=['run', 'test'])), - (("", "--no-strip-xpi",), dict(dest="no_strip_xpi", - help="retain unused modules in XPI", - action="store_true", - default=False, - cmds=['xpi'])), - (("", "--force-mobile",), dict(dest="enable_mobile", - help="Force compatibility with Firefox Mobile", - action="store_true", - default=False, - cmds=['run', 'test', 'xpi', 'testall'])), - (("", "--mobile-app",), dict(dest="mobile_app_name", - help=("Name of your Android application to " - "use. Possible values: 'firefox', " - "'firefox_beta', 'fennec_aurora', " - "'fennec' (for nightly)."), - metavar=None, - default=None, - cmds=['run', 'test', 'testall'])), - (("", "--harness-option",), dict(dest="extra_harness_option_args", - help=("Extra properties added to " - "harness-options.json"), - action="append", - metavar="KEY=VALUE", - default=[], - cmds=['xpi'])), - (("", "--stop-on-error",), dict(dest="stopOnError", - help="Stop running tests after the first failure", - action="store_true", - metavar=None, - default=False, - cmds=['test', 'testex', 'testpkgs'])), - (("", "--check-memory",), dict(dest="check_memory", - help="attempts to detect leaked compartments after a test run", - action="store_true", - default=False, - cmds=['test', 'testpkgs', 'testaddons', - 'testall'])), - (("", "--output-file",), dict(dest="output_file", - help="Where to put the finished .xpi", - default=None, - cmds=['xpi'])), - (("", "--abort-on-missing-module",), dict(dest="abort_on_missing", - help="Abort if required module is missing", - action="store_true", - default=False, - cmds=['test', 'run', 'xpi', 'testpkgs'])), - (("", "--no-connections",), dict(dest="no_connections", - help="disable/enable remote connections (on for cfx run only by default)", - type="choice", - choices=["on", "off", "default"], - default="default", - cmds=['test', 'run', 'testpkgs', - 'testall', 'testaddons', 'testex'])), - ] - ), - - ("Internal Command-Specific Options", [ - (("", "--addons",), dict(dest="addons", - help=("paths of addons to install, " - "comma-separated"), - metavar=None, - default=None, - cmds=['test', 'run', 'testex', 'testpkgs', - 'testall'])), - (("", "--test-runner-pkg",), dict(dest="test_runner_pkg", - help=("name of package " - "containing test runner " - "program (default is " - "test-harness)"), - default="addon-sdk", - cmds=['test', 'testex', 'testpkgs', - 'testall'])), - # --keydir was removed in 1.0b5, but we keep it around in the options - # parser to make life easier for frontends like FlightDeck which - # might still pass it. It can go away once the frontends are updated. - (("", "--keydir",), dict(dest="keydir", - help=("obsolete, ignored"), - metavar=None, - default=None, - cmds=['test', 'run', 'xpi', 'testex', - 'testpkgs', 'testall'])), - (("", "--e10s",), dict(dest="enable_e10s", - help="enable remote windows", - action="store_true", - default=False, - cmds=['test', 'run', 'testex', 'testpkgs', - 'testaddons', 'testcfx', 'testall'])), - (("", "--logfile",), dict(dest="logfile", - help="log console output to file", - metavar=None, - default=None, - cmds=['run', 'test', 'testex', 'testpkgs'])), - # TODO: This should default to true once our memory debugging - # issues are resolved; see bug 592774. - (("", "--profile-memory",), dict(dest="profileMemory", - help=("profile memory usage " - "(default is false)"), - type="int", - action="store", - default=0, - cmds=['test', 'testex', 'testpkgs', - 'testall'])), - ] - ), - ) - -def find_parent_package(cur_dir): - tail = True - while tail: - if os.path.exists(os.path.join(cur_dir, 'package.json')): - return cur_dir - cur_dir, tail = os.path.split(cur_dir) - return None - -def check_json(option, opt, value): - # We return the parsed JSON here; see bug 610816 for background on why. - try: - return json.loads(value) - except ValueError: - raise optparse.OptionValueError("Option %s must be JSON." % opt) - -class CfxOption(optparse.Option): - TYPES = optparse.Option.TYPES + ('json',) - TYPE_CHECKER = copy(optparse.Option.TYPE_CHECKER) - TYPE_CHECKER['json'] = check_json - -def parse_args(arguments, global_options, usage, version, parser_groups, - defaults=None): - parser = optparse.OptionParser(usage=usage.strip(), option_class=CfxOption, - version=version) - - def name_cmp(a, b): - # a[0] = name sequence - # a[0][0] = short name (possibly empty string) - # a[0][1] = long name - names = [] - for seq in (a, b): - names.append(seq[0][0][1:] if seq[0][0] else seq[0][1][2:]) - return cmp(*names) - - global_options.sort(name_cmp) - for names, opts in global_options: - parser.add_option(*names, **opts) - - for group_name, options in parser_groups: - group = optparse.OptionGroup(parser, group_name) - options.sort(name_cmp) - for names, opts in options: - if 'cmds' in opts: - cmds = opts['cmds'] - del opts['cmds'] - cmds.sort() - if not 'help' in opts: - opts['help'] = "" - opts['help'] += " (%s)" % ", ".join(cmds) - group.add_option(*names, **opts) - parser.add_option_group(group) - - if defaults: - parser.set_defaults(**defaults) - - (options, args) = parser.parse_args(args=arguments) - - if not args: - parser.print_help() - parser.exit() - - return (options, args) - -# all tests emit progress messages to stderr, not stdout. (the mozrunner -# console output goes to stderr and is hard to change, and -# unittest.TextTestRunner prefers stderr, so we send everything else there -# too, to keep all the messages in order) - -def test_all(env_root, defaults): - fail = False - - starttime = time.time() - - if not defaults['filter']: - print >>sys.stderr, "Testing cfx..." - sys.stderr.flush() - result = test_cfx(env_root, defaults['verbose']) - if result.failures or result.errors: - fail = True - - if not fail or not defaults.get("stopOnError"): - print >>sys.stderr, "Testing all examples..." - sys.stderr.flush() - - try: - test_all_examples(env_root, defaults) - except SystemExit, e: - fail = (e.code != 0) or fail - - if not fail or not defaults.get("stopOnError"): - print >>sys.stderr, "Testing all unit-test addons..." - sys.stderr.flush() - - try: - test_all_testaddons(env_root, defaults) - except SystemExit, e: - fail = (e.code != 0) or fail - - if not fail or not defaults.get("stopOnError"): - print >>sys.stderr, "Testing all packages..." - sys.stderr.flush() - try: - test_all_packages(env_root, defaults) - except SystemExit, e: - fail = (e.code != 0) or fail - - print >>sys.stderr, "Total time for all tests: %f seconds" % (time.time() - starttime) - - if fail: - print >>sys.stderr, "Some tests were unsuccessful." - sys.exit(1) - print >>sys.stderr, "All tests were successful. Ship it!" - sys.exit(0) - -def test_cfx(env_root, verbose): - import cuddlefish.tests - - # tests write to stderr. flush everything before and after to avoid - # confusion later. - sys.stdout.flush(); sys.stderr.flush() - olddir = os.getcwd() - os.chdir(env_root) - retval = cuddlefish.tests.run(verbose) - os.chdir(olddir) - sys.stdout.flush(); sys.stderr.flush() - return retval - -def test_all_testaddons(env_root, defaults): - addons_dir = os.path.join(env_root, "test", "addons") - addons = [dirname for dirname in os.listdir(addons_dir) - if os.path.isdir(os.path.join(addons_dir, dirname))] - addons.sort() - fail = False - for dirname in addons: - # apply the filter - if (not defaults['filter'].split(":")[0] in dirname): - continue - - print >>sys.stderr, "Testing %s..." % dirname - sys.stderr.flush() - try: - run(arguments=["testrun", - "--pkgdir", - os.path.join(addons_dir, dirname)], - defaults=defaults, - env_root=env_root) - except SystemExit, e: - fail = (e.code != 0) or fail - if fail and defaults.get("stopOnError"): - break - - if fail: - print >>sys.stderr, "Some test addons tests were unsuccessful." - sys.exit(-1) - -def test_all_examples(env_root, defaults): - examples_dir = os.path.join(env_root, "examples") - examples = [dirname for dirname in os.listdir(examples_dir) - if os.path.isdir(os.path.join(examples_dir, dirname))] - examples.sort() - fail = False - for dirname in examples: - if (not defaults['filter'].split(":")[0] in dirname): - continue - - print >>sys.stderr, "Testing %s..." % dirname - sys.stderr.flush() - try: - run(arguments=["test", - "--pkgdir", - os.path.join(examples_dir, dirname)], - defaults=defaults, - env_root=env_root) - except SystemExit, e: - fail = (e.code != 0) or fail - if fail and defaults.get("stopOnError"): - break - - if fail: - print >>sys.stderr, "Some examples tests were unsuccessful." - sys.exit(-1) - -def test_all_packages(env_root, defaults): - packages_dir = os.path.join(env_root, "packages") - if os.path.isdir(packages_dir): - packages = [dirname for dirname in os.listdir(packages_dir) - if os.path.isdir(os.path.join(packages_dir, dirname))] - else: - packages = [] - packages.append(env_root) - packages.sort() - print >>sys.stderr, "Testing all available packages: %s." % (", ".join(packages)) - sys.stderr.flush() - fail = False - for dirname in packages: - print >>sys.stderr, "Testing %s..." % dirname - sys.stderr.flush() - try: - run(arguments=["test", - "--pkgdir", - os.path.join(packages_dir, dirname)], - defaults=defaults, - env_root=env_root) - except SystemExit, e: - fail = (e.code != 0) or fail - if fail and defaults.get('stopOnError'): - break - if fail: - print >>sys.stderr, "Some package tests were unsuccessful." - sys.exit(-1) - -def get_config_args(name, env_root): - local_json = os.path.join(env_root, "local.json") - if not (os.path.exists(local_json) and - os.path.isfile(local_json)): - if name == "default": - return [] - else: - print >>sys.stderr, "File does not exist: %s" % local_json - sys.exit(1) - local_json = packaging.load_json_file(local_json) - if 'configs' not in local_json: - print >>sys.stderr, "'configs' key not found in local.json." - sys.exit(1) - if name not in local_json.configs: - if name == "default": - return [] - else: - print >>sys.stderr, "No config found for '%s'." % name - sys.exit(1) - config = local_json.configs[name] - if type(config) != list: - print >>sys.stderr, "Config for '%s' must be a list of strings." % name - sys.exit(1) - return config - -def initializer(env_root, args, out=sys.stdout, err=sys.stderr): - from templates import PACKAGE_JSON, TEST_MAIN_JS - from preflight import create_jid - path = os.getcwd() - addon = os.path.basename(path) - # if more than two arguments - if len(args) > 2: - print >>err, 'Too many arguments.' - return {"result":1} - if len(args) == 2: - path = os.path.join(path,args[1]) - try: - os.mkdir(path) - print >>out, '*', args[1], 'package directory created' - except OSError: - print >>out, '*', args[1], 'already exists, testing if directory is empty' - # avoid clobbering existing files, but we tolerate things like .git - existing = [fn for fn in os.listdir(path) if not fn.startswith(".")] - if existing: - print >>err, 'This command must be run in an empty directory.' - return {"result":1} - for d in ['lib','data','test']: - os.mkdir(os.path.join(path,d)) - print >>out, '*', d, 'directory created' - jid = create_jid() - print >>out, '* generated jID automatically:', jid - open(os.path.join(path,'package.json'),'w').write(PACKAGE_JSON % {'name':addon.lower(), - 'title':addon, - 'id':jid }) - print >>out, '* package.json written' - open(os.path.join(path,'test','test-main.js'),'w').write(TEST_MAIN_JS) - print >>out, '* test/test-main.js written' - open(os.path.join(path,'lib','main.js'),'w').write('') - print >>out, '* lib/main.js written' - if len(args) == 1: - print >>out, '\nYour sample add-on is now ready.' - print >>out, 'Do "cfx test" to test it and "cfx run" to try it. Have fun!' - else: - print >>out, '\nYour sample add-on is now ready in the \'' + args[1] + '\' directory.' - print >>out, 'Change to that directory, then do "cfx test" to test it, \nand "cfx run" to try it. Have fun!' - return {"result":0, "jid":jid} - -def buildJID(target_cfg): - if "id" in target_cfg: - jid = target_cfg["id"] - else: - import uuid - jid = str(uuid.uuid4()) - if not ("@" in jid or jid.startswith("{")): - jid = jid + "@jetpack" - return jid - -def run(arguments=sys.argv[1:], target_cfg=None, pkg_cfg=None, - defaults=None, env_root=os.environ.get('CUDDLEFISH_ROOT'), - stdout=sys.stdout): - versions = get_versions() - sdk_version = versions["version"] - display_version = "Add-on SDK %s (%s)" % (sdk_version, versions["full"]) - parser_kwargs = dict(arguments=arguments, - global_options=global_options, - parser_groups=parser_groups, - usage=usage, - version=display_version, - defaults=defaults) - - (options, args) = parse_args(**parser_kwargs) - - config_args = get_config_args(options.config, env_root); - - # reparse configs with arguments from local.json - if config_args: - parser_kwargs['arguments'] += config_args - (options, args) = parse_args(**parser_kwargs) - - command = args[0] - - if command == "init": - initializer(env_root, args) - return - if command == "testpkgs": - test_all_packages(env_root, defaults=options.__dict__) - return - elif command == "testaddons": - test_all_testaddons(env_root, defaults=options.__dict__) - return - elif command == "testex": - test_all_examples(env_root, defaults=options.__dict__) - return - elif command == "testall": - test_all(env_root, defaults=options.__dict__) - return - elif command == "testcfx": - if options.filter: - print >>sys.stderr, "The filter option is not valid with the testcfx command" - return - test_cfx(env_root, options.verbose) - return - elif command not in ["xpi", "test", "run", "testrun"]: - print >>sys.stderr, "Unknown command: %s" % command - print >>sys.stderr, "Try using '--help' for assistance." - sys.exit(1) - - target_cfg_json = None - if not target_cfg: - if not options.pkgdir: - options.pkgdir = find_parent_package(os.getcwd()) - if not options.pkgdir: - print >>sys.stderr, ("cannot find 'package.json' in the" - " current directory or any parent.") - sys.exit(1) - else: - options.pkgdir = os.path.abspath(options.pkgdir) - if not os.path.exists(os.path.join(options.pkgdir, 'package.json')): - print >>sys.stderr, ("cannot find 'package.json' in" - " %s." % options.pkgdir) - sys.exit(1) - - target_cfg_json = os.path.join(options.pkgdir, 'package.json') - target_cfg = packaging.get_config_in_dir(options.pkgdir) - - # At this point, we're either building an XPI or running Jetpack code in - # a Mozilla application (which includes running tests). - - use_main = False - inherited_options = ['verbose', 'enable_e10s', 'parseable', 'check_memory', - 'no_quit', 'abort_on_missing'] - enforce_timeouts = False - - if command == "xpi": - use_main = True - elif command == "test": - if 'tests' not in target_cfg: - target_cfg['tests'] = [] - inherited_options.extend(['iterations', 'filter', 'profileMemory', - 'stopOnError']) - enforce_timeouts = True - elif command == "run": - use_main = True - elif command == "testrun": - use_main = True - enforce_timeouts = True - else: - assert 0, "shouldn't get here" - - if use_main and 'main' not in target_cfg: - # If the user supplies a template dir, then the main - # program may be contained in the template. - if not options.templatedir: - print >>sys.stderr, "package.json does not have a 'main' entry." - sys.exit(1) - - if not pkg_cfg: - pkg_cfg = packaging.build_config(env_root, target_cfg, options.packagepath) - - target = target_cfg.name - - # TODO: Consider keeping a cache of dynamic UUIDs, based - # on absolute filesystem pathname, in the root directory - # or something. - if command in ('xpi', 'run', 'testrun'): - from cuddlefish.preflight import preflight_config - if target_cfg_json: - config_was_ok, modified = preflight_config(target_cfg, - target_cfg_json) - if not config_was_ok: - if modified: - # we need to re-read package.json . The safest approach - # is to re-run the "cfx xpi"/"cfx run" command. - print >>sys.stderr, ("package.json modified: please re-run" - " 'cfx %s'" % command) - else: - print >>sys.stderr, ("package.json needs modification:" - " please update it and then re-run" - " 'cfx %s'" % command) - sys.exit(1) - # if we make it this far, we have a JID - else: - assert command == "test" - - jid = buildJID(target_cfg) - - targets = [target] - if command == "test": - targets.append(options.test_runner_pkg) - - extra_packages = [] - if options.extra_packages: - extra_packages = options.extra_packages.split(",") - if extra_packages: - targets.extend(extra_packages) - target_cfg.extra_dependencies = extra_packages - - deps = packaging.get_deps_for_targets(pkg_cfg, targets) - - from cuddlefish.manifest import build_manifest, ModuleNotFoundError, \ - BadChromeMarkerError - # Figure out what loader files should be scanned. This is normally - # computed inside packaging.generate_build_for_target(), by the first - # dependent package that defines a "loader" property in its package.json. - # This property is interpreted as a filename relative to the top of that - # file, and stored as a path in build.loader . generate_build_for_target() - # cannot be called yet (it needs the list of used_deps that - # build_manifest() computes, but build_manifest() needs the list of - # loader files that it computes). We could duplicate or factor out this - # build.loader logic, but that would be messy, so instead we hard-code - # the choice of loader for manifest-generation purposes. In practice, - # this means that alternative loaders probably won't work with - # --strip-xpi. - assert packaging.DEFAULT_LOADER == "addon-sdk" - assert pkg_cfg.packages["addon-sdk"].loader == "lib/sdk/loader/cuddlefish.js" - cuddlefish_js_path = os.path.join(pkg_cfg.packages["addon-sdk"].root_dir, - "lib", "sdk", "loader", "cuddlefish.js") - loader_modules = [("addon-sdk", "lib", "sdk/loader/cuddlefish", cuddlefish_js_path)] - scan_tests = command == "test" - - try: - manifest = build_manifest(target_cfg, pkg_cfg, deps, scan_tests, - None, loader_modules, - abort_on_missing=options.abort_on_missing) - except ModuleNotFoundError, e: - print str(e) - sys.exit(1) - except BadChromeMarkerError, e: - # An error had already been displayed on stderr in manifest code - sys.exit(1) - used_deps = manifest.get_used_packages() - if command == "test": - # The test runner doesn't appear to link against any actual packages, - # because it loads everything at runtime (invisible to the linker). - # If we believe that, we won't set up URI mappings for anything, and - # tests won't be able to run. - used_deps = deps - for xp in extra_packages: - if xp not in used_deps: - used_deps.append(xp) - - build = packaging.generate_build_for_target( - pkg_cfg, target, used_deps, - include_dep_tests=options.dep_tests, - is_running_tests=(command == "test") - ) - - harness_options = { - 'jetpackID': jid, - 'staticArgs': options.static_args, - 'name': target, - } - - harness_options.update(build) - - # When cfx is run from sdk root directory, we will strip sdk modules and - # override them with local modules. - # So that integration tools will continue to work and use local modules - if os.getcwd() == env_root: - options.bundle_sdk = True - options.force_use_bundled_sdk = False - options.overload_modules = True - - if options.pkgdir == env_root: - options.bundle_sdk = True - options.overload_modules = True - - extra_environment = {} - if command == "test": - # This should be contained in the test runner package. - harness_options['main'] = 'sdk/test/runner' - harness_options['mainPath'] = 'sdk/test/runner' - else: - harness_options['main'] = target_cfg.get('main') - harness_options['mainPath'] = manifest.top_path - extra_environment["CFX_COMMAND"] = command - - for option in inherited_options: - harness_options[option] = getattr(options, option) - - harness_options['metadata'] = packaging.get_metadata(pkg_cfg, used_deps) - - harness_options['sdkVersion'] = sdk_version - - packaging.call_plugins(pkg_cfg, used_deps) - - retval = 0 - - if options.templatedir: - app_extension_dir = os.path.abspath(options.templatedir) - elif os.path.exists(os.path.join(options.pkgdir, "app-extension")): - app_extension_dir = os.path.join(options.pkgdir, "app-extension") - else: - mydir = os.path.dirname(os.path.abspath(__file__)) - app_extension_dir = os.path.join(mydir, "../../app-extension") - - # Do not add entries for SDK modules - harness_options['manifest'] = manifest.get_harness_options_manifest(False) - - # Gives an hint to tell if sdk modules are bundled or not - harness_options['is-sdk-bundled'] = options.bundle_sdk or options.no_strip_xpi - - if options.force_use_bundled_sdk: - if not harness_options['is-sdk-bundled']: - print >>sys.stderr, ("--force-use-bundled-sdk " - "can't be used if sdk isn't bundled.") - sys.exit(1) - if options.overload_modules: - print >>sys.stderr, ("--force-use-bundled-sdk and --overload-modules " - "can't be used at the same time.") - sys.exit(1) - # Pass a flag in order to force using sdk modules shipped in the xpi - harness_options['force-use-bundled-sdk'] = True - - from cuddlefish.rdf import gen_manifest, RDFUpdate - - manifest_rdf = gen_manifest(template_root_dir=app_extension_dir, - target_cfg=target_cfg, - jid=jid, - update_url=options.update_url, - bootstrap=True, - enable_mobile=options.enable_mobile) - - if command == "xpi" and options.update_link: - if not options.update_link.startswith("https"): - raise optparse.OptionValueError("--update-link must start with 'https': %s" % options.update_link) - rdf_name = UPDATE_RDF_FILENAME % target_cfg.name - print >>stdout, "Exporting update description to %s." % rdf_name - update = RDFUpdate() - update.add(manifest_rdf, options.update_link) - open(rdf_name, "w").write(str(update)) - - # ask the manifest what files were used, so we can construct an XPI - # without the rest. This will include the loader (and everything it - # uses) because of the "loader_modules" starting points we passed to - # build_manifest earlier - used_files = None - if command == "xpi": - used_files = set(manifest.get_used_files(options.bundle_sdk)) - - if options.no_strip_xpi: - used_files = None # disables the filter, includes all files - - if command == 'xpi': - from cuddlefish.xpi import build_xpi - # Generate extra options - extra_harness_options = {} - for kv in options.extra_harness_option_args: - key,value = kv.split("=", 1) - extra_harness_options[key] = value - # Generate xpi filepath - if options.output_file: - xpi_path = options.output_file - else: - xpi_path = XPI_FILENAME % target_cfg.name - - print >>stdout, "Exporting extension to %s." % xpi_path - build_xpi(template_root_dir=app_extension_dir, - manifest=manifest_rdf, - xpi_path=xpi_path, - harness_options=harness_options, - limit_to=used_files, - extra_harness_options=extra_harness_options, - bundle_sdk=True, - pkgdir=options.pkgdir) - else: - from cuddlefish.runner import run_app - - if options.no_connections == "default": - if command == "run": - no_connections = False - else: - no_connections = True - elif options.no_connections == "on": - no_connections = True - else: - no_connections = False - - if options.profiledir: - options.profiledir = os.path.expanduser(options.profiledir) - options.profiledir = os.path.abspath(options.profiledir) - - if options.addons is not None: - options.addons = options.addons.split(",") - - enable_e10s = options.enable_e10s or target_cfg.get('e10s', False) - - try: - retval = run_app(harness_root_dir=app_extension_dir, - manifest_rdf=manifest_rdf, - harness_options=harness_options, - app_type=options.app, - binary=options.binary, - profiledir=options.profiledir, - verbose=options.verbose, - parseable=options.parseable, - enforce_timeouts=enforce_timeouts, - logfile=options.logfile, - addons=options.addons, - args=options.cmdargs, - extra_environment=extra_environment, - norun=options.no_run, - noquit=options.no_quit, - used_files=used_files, - enable_mobile=options.enable_mobile, - mobile_app_name=options.mobile_app_name, - env_root=env_root, - is_running_tests=(command == "test"), - overload_modules=options.overload_modules, - bundle_sdk=options.bundle_sdk, - pkgdir=options.pkgdir, - enable_e10s=enable_e10s, - no_connections=no_connections) - except ValueError, e: - print "" - print "A given cfx option has an inappropriate value:" - print >>sys.stderr, " " + " \n ".join(str(e).split("\n")) - retval = -1 - except Exception, e: - if str(e).startswith(MOZRUNNER_BIN_NOT_FOUND): - print >>sys.stderr, MOZRUNNER_BIN_NOT_FOUND_HELP.strip() - retval = -1 - else: - raise - sys.exit(retval) diff --git a/addon-sdk/source/python-lib/cuddlefish/_version.py b/addon-sdk/source/python-lib/cuddlefish/_version.py deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/_version.py +++ /dev/null @@ -1,174 +0,0 @@ - -# This file helps to compute a version number in source trees obtained from -# git-archive tarball (such as those provided by githubs download-from-tag -# feature). Distribution tarballs (build by setup.py sdist) and build -# directories (produced by setup.py build) will contain a much shorter file -# that just contains the computed version number. - -# This file is released into the public domain. Generated by versioneer-0.6 -# (https://github.com/warner/python-versioneer) - -# these strings will be replaced by git during git-archive -git_refnames = "$Format:%d$" -git_full = "$Format:%H$" - - -import subprocess - -def run_command(args, cwd=None, verbose=False): - try: - # remember shell=False, so use git.cmd on windows, not just git - p = subprocess.Popen(args, stdout=subprocess.PIPE, cwd=cwd) - except EnvironmentError, e: - if verbose: - print "unable to run %s" % args[0] - print e - return None - stdout = p.communicate()[0].strip() - if p.returncode != 0: - if verbose: - print "unable to run %s (error)" % args[0] - return None - return stdout - - -import sys -import re -import os.path - -def get_expanded_variables(versionfile_source): - """ - the code embedded in _version.py can just fetch the value of these - variables. When used from setup.py, we don't want to import - _version.py, so we do it with a regexp instead. This function is not - used from _version.py. - """ - variables = {} - try: - for line in open(versionfile_source,"r").readlines(): - if line.strip().startswith("git_refnames ="): - mo = re.search(r'=\s*"(.*)"', line) - if mo: - variables["refnames"] = mo.group(1) - if line.strip().startswith("git_full ="): - mo = re.search(r'=\s*"(.*)"', line) - if mo: - variables["full"] = mo.group(1) - except EnvironmentError: - pass - return variables - -def versions_from_expanded_variables(variables, tag_prefix): - refnames = variables["refnames"].strip() - if refnames.startswith("$Format"): - return {} # unexpanded, so not in an unpacked git-archive tarball - refs = set([r.strip() for r in refnames.strip("()").split(",")]) - for ref in list(refs): - if not re.search(r'\d', ref): - refs.discard(ref) - # Assume all version tags have a digit. git's %d expansion - # behaves like git log --decorate=short and strips out the - # refs/heads/ and refs/tags/ prefixes that would let us - # distinguish between branches and tags. By ignoring refnames - # without digits, we filter out many common branch names like - # "release" and "stabilization", as well as "HEAD" and "master". - for ref in sorted(refs): - # sorting will prefer e.g. "2.0" over "2.0rc1" - if ref.startswith(tag_prefix): - r = ref[len(tag_prefix):] - return { "version": r, - "full": variables["full"].strip() } - # no suitable tags, so we use the full revision id - return { "version": variables["full"].strip(), - "full": variables["full"].strip() } - -def versions_from_vcs(tag_prefix, versionfile_source, verbose=False): - """ - this runs 'git' from the root of the source tree. That either means - someone ran a setup.py command (and this code is in versioneer.py, thus - the containing directory is the root of the source tree), or someone - ran a project-specific entry point (and this code is in _version.py, - thus the containing directory is somewhere deeper in the source tree). - This only gets called if the git-archive 'subst' variables were *not* - expanded, and _version.py hasn't already been rewritten with a short - version string, meaning we're inside a checked out source tree. - """ - try: - here = os.path.abspath(__file__) - except NameError: - # some py2exe/bbfreeze/non-CPython implementations don't do __file__ - return {} # not always correct - - # versionfile_source is the relative path from the top of the source tree - # (where the .git directory might live) to this file. Invert this to find - # the root from __file__. - root = here - for i in range(len(versionfile_source.split("/"))): - root = os.path.dirname(root) - if not os.path.exists(os.path.join(root, ".git")): - return {} - - GIT = "git" - if sys.platform == "win32": - GIT = "git.cmd" - stdout = run_command([GIT, "describe", "--tags", "--dirty", "--always"], - cwd=root) - if stdout is None: - return {} - if not stdout.startswith(tag_prefix): - if verbose: - print "tag '%s' doesn't start with prefix '%s'" % (stdout, tag_prefix) - return {} - tag = stdout[len(tag_prefix):] - stdout = run_command([GIT, "rev-parse", "HEAD"], cwd=root) - if stdout is None: - return {} - full = stdout.strip() - if tag.endswith("-dirty"): - full += "-dirty" - return {"version": tag, "full": full} - - -def versions_from_parentdir(parentdir_prefix, versionfile_source, verbose=False): - try: - here = os.path.abspath(__file__) - # versionfile_source is the relative path from the top of the source - # tree (where the .git directory might live) to _version.py, when - # this is used by the runtime. Invert this to find the root from - # __file__. - root = here - for i in range(len(versionfile_source.split("/"))): - root = os.path.dirname(root) - except NameError: - # try a couple different things to handle py2exe, bbfreeze, and - # non-CPython implementations which don't do __file__. This code - # either lives in versioneer.py (used by setup.py) or _version.py - # (used by the runtime). In the versioneer.py case, sys.argv[0] will - # be setup.py, in the root of the source tree. In the _version.py - # case, we have no idea what sys.argv[0] is (some - # application-specific runner). - root = os.path.dirname(os.path.abspath(sys.argv[0])) - # Source tarballs conventionally unpack into a directory that includes - # both the project name and a version string. - dirname = os.path.basename(root) - if not dirname.startswith(parentdir_prefix): - if verbose: - print "dirname '%s' doesn't start with prefix '%s'" % (dirname, parentdir_prefix) - return None - return {"version": dirname[len(parentdir_prefix):], "full": ""} - -tag_prefix = "" -parentdir_prefix = "addon-sdk-" -versionfile_source = "python-lib/cuddlefish/_version.py" - -def get_versions(): - variables = { "refnames": git_refnames, "full": git_full } - ver = versions_from_expanded_variables(variables, tag_prefix) - if not ver: - ver = versions_from_vcs(tag_prefix, versionfile_source) - if not ver: - ver = versions_from_parentdir(parentdir_prefix, versionfile_source) - if not ver: - ver = {"version": "unknown", "full": ""} - return ver - diff --git a/addon-sdk/source/python-lib/cuddlefish/bunch.py b/addon-sdk/source/python-lib/cuddlefish/bunch.py deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/bunch.py +++ /dev/null @@ -1,34 +0,0 @@ -# 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/. - -# Taken from Paver's paver.options module. - -class Bunch(dict): - """A dictionary that provides attribute-style access.""" - - def __repr__(self): - keys = self.keys() - keys.sort() - args = ', '.join(['%s=%r' % (key, self[key]) for key in keys]) - return '%s(%s)' % (self.__class__.__name__, args) - - def __getitem__(self, key): - item = dict.__getitem__(self, key) - if callable(item): - return item() - return item - - def __getattr__(self, name): - try: - return self[name] - except KeyError: - raise AttributeError(name) - - __setattr__ = dict.__setitem__ - - def __delattr__(self, name): - try: - del self[name] - except KeyError: - raise AttributeError(name) diff --git a/addon-sdk/source/python-lib/cuddlefish/manifest.py b/addon-sdk/source/python-lib/cuddlefish/manifest.py deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/manifest.py +++ /dev/null @@ -1,807 +0,0 @@ -# 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/. - - -import os, sys, re, hashlib -import simplejson as json -SEP = os.path.sep -from cuddlefish.util import filter_filenames, filter_dirnames - -# Load new layout mapping hashtable -path = os.path.join(os.environ.get('CUDDLEFISH_ROOT'), "mapping.json") -data = open(path, 'r').read() -NEW_LAYOUT_MAPPING = json.loads(data) - -def js_zipname(packagename, modulename): - return "%s-lib/%s.js" % (packagename, modulename) -def docs_zipname(packagename, modulename): - return "%s-docs/%s.md" % (packagename, modulename) -def datamap_zipname(packagename): - return "%s-data.json" % packagename -def datafile_zipname(packagename, datapath): - return "%s-data/%s" % (packagename, datapath) - -def to_json(o): - return json.dumps(o, indent=1).encode("utf-8")+"\n" - -class ModuleNotFoundError(Exception): - def __init__(self, requirement_type, requirement_name, - used_by, line_number, looked_in): - Exception.__init__(self) - self.requirement_type = requirement_type # "require" or "define" - self.requirement_name = requirement_name # string, what they require()d - self.used_by = used_by # string, full path to module which did require() - self.line_number = line_number # int, 1-indexed line number of first require() - self.looked_in = looked_in # list of full paths to potential .js files - def __str__(self): - what = "%s(%s)" % (self.requirement_type, self.requirement_name) - where = self.used_by - if self.line_number is not None: - where = "%s:%d" % (self.used_by, self.line_number) - searched = "Looked for it in:\n %s\n" % "\n ".join(self.looked_in) - return ("ModuleNotFoundError: unable to satisfy: %s from\n" - " %s:\n" % (what, where)) + searched - -class BadModuleIdentifier(Exception): - pass -class BadSection(Exception): - pass -class UnreachablePrefixError(Exception): - pass - -class ManifestEntry: - def __init__(self): - self.docs_filename = None - self.docs_hash = None - self.requirements = {} - self.datamap = None - - def get_path(self): - name = self.moduleName - - if name.endswith(".js"): - name = name[:-3] - items = [] - # Only add package name for addons, so that system module paths match - # the path from the commonjs root directory and also match the loader - # mappings. - if self.packageName != "addon-sdk": - items.append(self.packageName) - # And for the same reason, do not append `lib/`. - if self.sectionName == "tests": - items.append(self.sectionName) - items.append(name) - - return "/".join(items) - - def get_entry_for_manifest(self): - entry = { "packageName": self.packageName, - "sectionName": self.sectionName, - "moduleName": self.moduleName, - "jsSHA256": self.js_hash, - "docsSHA256": self.docs_hash, - "requirements": {}, - } - for req in self.requirements: - if isinstance(self.requirements[req], ManifestEntry): - them = self.requirements[req] # this is another ManifestEntry - entry["requirements"][req] = them.get_path() - else: - # something magic. The manifest entry indicates that they're - # allowed to require() it - entry["requirements"][req] = self.requirements[req] - assert isinstance(entry["requirements"][req], unicode) or \ - isinstance(entry["requirements"][req], str) - return entry - - def add_js(self, js_filename): - self.js_filename = js_filename - self.js_hash = hash_file(js_filename) - def add_docs(self, docs_filename): - self.docs_filename = docs_filename - self.docs_hash = hash_file(docs_filename) - def add_requirement(self, reqname, reqdata): - self.requirements[reqname] = reqdata - def add_data(self, datamap): - self.datamap = datamap - - def get_js_zipname(self): - return js_zipname(self.packagename, self.modulename) - def get_docs_zipname(self): - if self.docs_hash: - return docs_zipname(self.packagename, self.modulename) - return None - # self.js_filename - # self.docs_filename - - -def hash_file(fn): - return hashlib.sha256(open(fn,"rb").read()).hexdigest() - -def get_datafiles(datadir): - """ - yields pathnames relative to DATADIR, ignoring some files - """ - for dirpath, dirnames, filenames in os.walk(datadir): - filenames = list(filter_filenames(filenames)) - # this tells os.walk to prune the search - dirnames[:] = filter_dirnames(dirnames) - for filename in filenames: - fullname = os.path.join(dirpath, filename) - assert fullname.startswith(datadir+SEP), "%s%s not in %s" % (datadir, SEP, fullname) - yield fullname[len(datadir+SEP):] - - -class DataMap: - # one per package - def __init__(self, pkg): - self.pkg = pkg - self.name = pkg.name - self.files_to_copy = [] - datamap = {} - datadir = os.path.join(pkg.root_dir, "data") - for dataname in get_datafiles(datadir): - absname = os.path.join(datadir, dataname) - zipname = datafile_zipname(pkg.name, dataname) - datamap[dataname] = hash_file(absname) - self.files_to_copy.append( (zipname, absname) ) - self.data_manifest = to_json(datamap) - self.data_manifest_hash = hashlib.sha256(self.data_manifest).hexdigest() - self.data_manifest_zipname = datamap_zipname(pkg.name) - self.data_uri_prefix = "%s/data/" % (self.name) - -class BadChromeMarkerError(Exception): - pass - -class ModuleInfo: - def __init__(self, package, section, name, js, docs): - self.package = package - self.section = section - self.name = name - self.js = js - self.docs = docs - - def __hash__(self): - return hash( (self.package.name, self.section, self.name, - self.js, self.docs) ) - def __eq__(self, them): - if them.__class__ is not self.__class__: - return False - if ((them.package.name, them.section, them.name, them.js, them.docs) != - (self.package.name, self.section, self.name, self.js, self.docs) ): - return False - return True - - def __repr__(self): - return "ModuleInfo [%s %s %s] (%s, %s)" % (self.package.name, - self.section, - self.name, - self.js, self.docs) - -class ManifestBuilder: - def __init__(self, target_cfg, pkg_cfg, deps, extra_modules, - stderr=sys.stderr, abort_on_missing=False): - self.manifest = {} # maps (package,section,module) to ManifestEntry - self.target_cfg = target_cfg # the entry point - self.pkg_cfg = pkg_cfg # all known packages - self.deps = deps # list of package names to search - self.used_packagenames = set() - self.stderr = stderr - self.extra_modules = extra_modules - self.modules = {} # maps ModuleInfo to URI in self.manifest - self.datamaps = {} # maps package name to DataMap instance - self.files = [] # maps manifest index to (absfn,absfn) js/docs pair - self.test_modules = [] # for runtime - self.abort_on_missing = abort_on_missing # cfx eol - - def build(self, scan_tests, test_filter_re): - """ - process the top module, which recurses to process everything it reaches - """ - if "main" in self.target_cfg: - top_mi = self.find_top(self.target_cfg) - top_me = self.process_module(top_mi) - self.top_path = top_me.get_path() - self.datamaps[self.target_cfg.name] = DataMap(self.target_cfg) - if scan_tests: - mi = self._find_module_in_package("addon-sdk", "lib", "sdk/test/runner", []) - self.process_module(mi) - # also scan all test files in all packages that we use. By making - # a copy of self.used_packagenames first, we refrain from - # processing tests in packages that our own tests depend upon. If - # we're running tests for package A, and either modules in A or - # tests in A depend upon modules from package B, we *don't* want - # to run tests for package B. - test_modules = [] - dirnames = self.target_cfg["tests"] - if isinstance(dirnames, basestring): - dirnames = [dirnames] - dirnames = [os.path.join(self.target_cfg.root_dir, d) - for d in dirnames] - for d in dirnames: - for filename in os.listdir(d): - if filename.startswith("test-") and filename.endswith(".js"): - testname = filename[:-3] # require(testname) - if test_filter_re: - if not re.search(test_filter_re, testname): - continue - tmi = ModuleInfo(self.target_cfg, "tests", testname, - os.path.join(d, filename), None) - # scan the test's dependencies - tme = self.process_module(tmi) - test_modules.append( (testname, tme) ) - # also add it as an artificial dependency of unit-test-finder, so - # the runtime dynamic load can work. - test_finder = self.get_manifest_entry("addon-sdk", "lib", - "sdk/deprecated/unit-test-finder") - for (testname,tme) in test_modules: - test_finder.add_requirement(testname, tme) - # finally, tell the runtime about it, so they won't have to - # search for all tests. self.test_modules will be passed - # through the harness-options.json file in the - # .allTestModules property. - # Pass the absolute module path. - self.test_modules.append(tme.get_path()) - - # include files used by the loader - for em in self.extra_modules: - (pkgname, section, modname, js) = em - mi = ModuleInfo(self.pkg_cfg.packages[pkgname], section, modname, - js, None) - self.process_module(mi) - - - def get_module_entries(self): - return frozenset(self.manifest.values()) - def get_data_entries(self): - return frozenset(self.datamaps.values()) - - def get_used_packages(self): - used = set() - for index in self.manifest: - (package, section, module) = index - used.add(package) - return sorted(used) - - def get_used_files(self, bundle_sdk_modules): - """ - returns all .js files that we reference, plus data/ files. You will - need to add the loader, off-manifest files that it needs, and - generated metadata. - """ - for datamap in self.datamaps.values(): - for (zipname, absname) in datamap.files_to_copy: - yield absname - - for me in self.get_module_entries(): - # Only ship SDK files if we are told to do so - if me.packageName != "addon-sdk" or bundle_sdk_modules: - yield me.js_filename - - def get_harness_options_manifest(self, bundle_sdk_modules): - manifest = {} - for me in self.get_module_entries(): - path = me.get_path() - # Do not add manifest entries for system modules. - # Doesn't prevent from shipping modules. - # Shipping modules is decided in `get_used_files`. - if me.packageName != "addon-sdk" or bundle_sdk_modules: - manifest[path] = me.get_entry_for_manifest() - return manifest - - def get_manifest_entry(self, package, section, module): - index = (package, section, module) - if index not in self.manifest: - m = self.manifest[index] = ManifestEntry() - m.packageName = package - m.sectionName = section - m.moduleName = module - self.used_packagenames.add(package) - return self.manifest[index] - - def uri_name_from_path(self, pkg, fn): - # given a filename like .../pkg1/lib/bar/foo.js, and a package - # specification (with a .root_dir like ".../pkg1" and a .lib list of - # paths where .lib[0] is like "lib"), return the appropriate NAME - # that can be put into a URI like resource://JID-pkg1-lib/NAME . This - # will throw an exception if the file is outside of the lib/ - # directory, since that means we can't construct a URI that points to - # it. - # - # This should be a lot easier, and shouldn't fail when the file is in - # the root of the package. Both should become possible when the XPI - # is rearranged and our URI scheme is simplified. - fn = os.path.abspath(fn) - pkglib = pkg.lib[0] - libdir = os.path.abspath(os.path.join(pkg.root_dir, pkglib)) - # AARGH, section and name! we need to reverse-engineer a - # ModuleInfo instance that will produce a URI (in the form - # PREFIX/PKGNAME-SECTION/JS) that will map to the existing file. - # Until we fix URI generation to get rid of "sections", this is - # limited to files in the same .directories.lib as the rest of - # the package uses. So if the package's main files are in lib/, - # but the main.js is in the package root, there is no URI we can - # construct that will point to it, and we must fail. - # - # This will become much easier (and the failure case removed) - # when we get rid of sections and change the URIs to look like - # (PREFIX/PKGNAME/PATH-TO-JS). - - # AARGH 2, allowing .lib to be a list is really getting in the - # way. That needs to go away eventually too. - if not fn.startswith(libdir): - raise UnreachablePrefixError("Sorry, but the 'main' file (%s) in package %s is outside that package's 'lib' directory (%s), so I cannot construct a URI to reach it." - % (fn, pkg.name, pkglib)) - name = fn[len(libdir):].lstrip(SEP)[:-len(".js")] - return name - - - def parse_main(self, root_dir, main, check_lib_dir=None): - # 'main' can be like one of the following: - # a: ./lib/main.js b: ./lib/main c: lib/main - # we require it to be a path to the file, though, and ignore the - # .directories stuff. So just "main" is insufficient if you really - # want something in a "lib/" subdirectory. - if main.endswith(".js"): - main = main[:-len(".js")] - if main.startswith("./"): - main = main[len("./"):] - # package.json must always use "/", but on windows we'll replace that - # with "\" before using it as an actual filename - main = os.sep.join(main.split("/")) - paths = [os.path.join(root_dir, main+".js")] - if check_lib_dir is not None: - paths.append(os.path.join(root_dir, check_lib_dir, main+".js")) - return paths - - def find_top_js(self, target_cfg): - for libdir in target_cfg.lib: - for n in self.parse_main(target_cfg.root_dir, target_cfg.main, - libdir): - if os.path.exists(n): - return n - raise KeyError("unable to find main module '%s.js' in top-level package" % target_cfg.main) - - def find_top(self, target_cfg): - top_js = self.find_top_js(target_cfg) - n = os.path.join(target_cfg.root_dir, "README.md") - if os.path.exists(n): - top_docs = n - else: - top_docs = None - name = self.uri_name_from_path(target_cfg, top_js) - return ModuleInfo(target_cfg, "lib", name, top_js, top_docs) - - def process_module(self, mi): - pkg = mi.package - #print "ENTERING", pkg.name, mi.name - # mi.name must be fully-qualified - assert (not mi.name.startswith("./") and - not mi.name.startswith("../")) - # create and claim the manifest row first - me = self.get_manifest_entry(pkg.name, mi.section, mi.name) - - me.add_js(mi.js) - if mi.docs: - me.add_docs(mi.docs) - - js_lines = open(mi.js,"r").readlines() - requires, problems, locations = scan_module(mi.js,js_lines,self.stderr) - if problems: - # the relevant instructions have already been written to stderr - raise BadChromeMarkerError() - - # We update our requirements on the way out of the depth-first - # traversal of the module graph - - for reqname in sorted(requires.keys()): - # If requirement is chrome or a pseudo-module (starts with @) make - # path a requirement name. - if reqname == "chrome" or reqname.startswith("@"): - me.add_requirement(reqname, reqname) - else: - # when two modules require() the same name, do they get a - # shared instance? This is a deep question. For now say yes. - - # find_req_for() returns an entry to put in our - # 'requirements' dict, and will recursively process - # everything transitively required from here. It will also - # populate the self.modules[] cache. Note that we must - # tolerate cycles in the reference graph. - looked_in = [] # populated by subroutines - them_me = self.find_req_for(mi, reqname, looked_in, locations) - if them_me is None: - if mi.section == "tests": - # tolerate missing modules in tests, because - # test-securable-module.js, and the modules/red.js - # that it imports, both do that intentionally - continue - if reqname.endswith(".jsm"): - # ignore JSM modules - continue - if not self.abort_on_missing: - # print a warning, but tolerate missing modules - # unless cfx --abort-on-missing-module flag was set - print >>self.stderr, "Warning: missing module: %s" % reqname - me.add_requirement(reqname, reqname) - continue - lineno = locations.get(reqname) # None means define() - if lineno is None: - reqtype = "define" - else: - reqtype = "require" - err = ModuleNotFoundError(reqtype, reqname, - mi.js, lineno, looked_in) - raise err - else: - me.add_requirement(reqname, them_me) - - return me - #print "LEAVING", pkg.name, mi.name - - def find_req_for(self, from_module, reqname, looked_in, locations): - # handle a single require(reqname) statement from from_module . - # Return a uri that exists in self.manifest - # Populate looked_in with places we looked. - def BAD(msg): - return BadModuleIdentifier(msg + " in require(%s) from %s" % - (reqname, from_module)) - - if not reqname: - raise BAD("no actual modulename") - - # Allow things in tests/*.js to require both test code and real code. - # But things in lib/*.js can only require real code. - if from_module.section == "tests": - lookfor_sections = ["tests", "lib"] - elif from_module.section == "lib": - lookfor_sections = ["lib"] - else: - raise BadSection(from_module.section) - modulename = from_module.name - - #print " %s require(%s))" % (from_module, reqname) - - if reqname.startswith("./") or reqname.startswith("../"): - # 1: they want something relative to themselves, always from - # their own package - them = modulename.split("/")[:-1] - bits = reqname.split("/") - while bits[0] in (".", ".."): - if not bits: - raise BAD("no actual modulename") - if bits[0] == "..": - if not them: - raise BAD("too many ..") - them.pop() - bits.pop(0) - bits = them+bits - lookfor_pkg = from_module.package.name - lookfor_mod = "/".join(bits) - return self._get_module_from_package(lookfor_pkg, - lookfor_sections, lookfor_mod, - looked_in) - - # non-relative import. Might be a short name (requiring a search - # through "library" packages), or a fully-qualified one. - - if "/" in reqname: - # 2: PKG/MOD: find PKG, look inside for MOD - bits = reqname.split("/") - lookfor_pkg = bits[0] - lookfor_mod = "/".join(bits[1:]) - mi = self._get_module_from_package(lookfor_pkg, - lookfor_sections, lookfor_mod, - looked_in) - if mi: # caution, 0==None - return mi - else: - # 3: try finding PKG, if found, use its main.js entry point - lookfor_pkg = reqname - mi = self._get_entrypoint_from_package(lookfor_pkg, looked_in) - if mi: - return mi - - # 4: search packages for MOD or MODPARENT/MODCHILD. We always search - # their own package first, then the list of packages defined by their - # .dependencies list - from_pkg = from_module.package.name - mi = self._search_packages_for_module(from_pkg, - lookfor_sections, reqname, - looked_in) - if mi: - return mi - - # Only after we look for module in the addon itself, search for a module - # in new layout. - # First normalize require argument in order to easily find a mapping - normalized = reqname - if normalized.endswith(".js"): - normalized = normalized[:-len(".js")] - if normalized.startswith("addon-kit/"): - normalized = normalized[len("addon-kit/"):] - if normalized.startswith("api-utils/"): - normalized = normalized[len("api-utils/"):] - if normalized in NEW_LAYOUT_MAPPING: - # get the new absolute path for this module - original_reqname = reqname - reqname = NEW_LAYOUT_MAPPING[normalized] - from_pkg = from_module.package.name - - # If the addon didn't explicitely told us to ignore deprecated - # require path, warn the developer: - # (target_cfg is the package.json file) - if not "ignore-deprecated-path" in self.target_cfg: - lineno = locations.get(original_reqname) - print >>self.stderr, "Warning: Use of deprecated require path:" - print >>self.stderr, " In %s:%d:" % (from_module.js, lineno) - print >>self.stderr, " require('%s')." % original_reqname - print >>self.stderr, " New path should be:" - print >>self.stderr, " require('%s')" % reqname - - return self._search_packages_for_module(from_pkg, - lookfor_sections, reqname, - looked_in) - else: - # We weren't able to find this module, really. - return None - - def _handle_module(self, mi): - if not mi: - return None - - # we tolerate cycles in the reference graph, which means we need to - # populate the self.modules cache before recursing into - # process_module() . We must also check the cache first, so recursion - # can terminate. - if mi in self.modules: - return self.modules[mi] - - # this creates the entry - new_entry = self.get_manifest_entry(mi.package.name, mi.section, mi.name) - # and populates the cache - self.modules[mi] = new_entry - self.process_module(mi) - return new_entry - - def _get_module_from_package(self, pkgname, sections, modname, looked_in): - if pkgname not in self.pkg_cfg.packages: - return None - mi = self._find_module_in_package(pkgname, sections, modname, - looked_in) - return self._handle_module(mi) - - def _get_entrypoint_from_package(self, pkgname, looked_in): - if pkgname not in self.pkg_cfg.packages: - return None - pkg = self.pkg_cfg.packages[pkgname] - main = pkg.get("main", None) - if not main: - return None - for js in self.parse_main(pkg.root_dir, main): - looked_in.append(js) - if os.path.exists(js): - section = "lib" - name = self.uri_name_from_path(pkg, js) - docs = None - mi = ModuleInfo(pkg, section, name, js, docs) - return self._handle_module(mi) - return None - - def _search_packages_for_module(self, from_pkg, sections, reqname, - looked_in): - searchpath = [] # list of package names - searchpath.append(from_pkg) # search self first - us = self.pkg_cfg.packages[from_pkg] - if 'dependencies' in us: - # only look in dependencies - searchpath.extend(us['dependencies']) - else: - # they didn't declare any dependencies (or they declared an empty - # list, but we'll treat that as not declaring one, because it's - # easier), so look in all deps, sorted alphabetically, so - # addon-kit comes first. Note that self.deps includes all - # packages found by traversing the ".dependencies" lists in each - # package.json, starting from the main addon package, plus - # everything added by --extra-packages - searchpath.extend(sorted(self.deps)) - for pkgname in searchpath: - mi = self._find_module_in_package(pkgname, sections, reqname, - looked_in) - if mi: - return self._handle_module(mi) - return None - - def _find_module_in_package(self, pkgname, sections, name, looked_in): - # require("a/b/c") should look at ...\a\b\c.js on windows - filename = os.sep.join(name.split("/")) - # normalize filename, make sure that we do not add .js if it already has - # it. - if not filename.endswith(".js") and not filename.endswith(".json"): - filename += ".js" - - if filename.endswith(".js"): - basename = filename[:-3] - if filename.endswith(".json"): - basename = filename[:-5] - - pkg = self.pkg_cfg.packages[pkgname] - if isinstance(sections, basestring): - sections = [sections] - for section in sections: - for sdir in pkg.get(section, []): - js = os.path.join(pkg.root_dir, sdir, filename) - looked_in.append(js) - if os.path.exists(js): - docs = None - maybe_docs = os.path.join(pkg.root_dir, "docs", - basename+".md") - if section == "lib" and os.path.exists(maybe_docs): - docs = maybe_docs - return ModuleInfo(pkg, section, name, js, docs) - return None - -def build_manifest(target_cfg, pkg_cfg, deps, scan_tests, - test_filter_re=None, extra_modules=[], abort_on_missing=False): - """ - Perform recursive dependency analysis starting from entry_point, - building up a manifest of modules that need to be included in the XPI. - Each entry will map require() names to the URL of the module that will - be used to satisfy that dependency. The manifest will be used by the - runtime's require() code. - - This returns a ManifestBuilder object, with two public methods. The - first, get_module_entries(), returns a set of ManifestEntry objects, each - of which can be asked for the following: - - * its contribution to the harness-options.json '.manifest' - * the local disk name - * the name in the XPI at which it should be placed - - The second is get_data_entries(), which returns a set of DataEntry - objects, each of which has: - - * local disk name - * name in the XPI - - note: we don't build the XPI here, but our manifest is passed to the - code which does, so it knows what to copy into the XPI. - """ - - mxt = ManifestBuilder(target_cfg, pkg_cfg, deps, extra_modules, - abort_on_missing=abort_on_missing) - mxt.build(scan_tests, test_filter_re) - return mxt - - - -COMMENT_PREFIXES = ["//", "/*", "*", "dump("] - -REQUIRE_RE = r"(?>stderr, """ -The following lines from file %(fn)s: -%(lines)s -use 'Components' to access chrome authority. To do so, you need to add a -line somewhat like the following: - - const {%(needs)s} = require("chrome"); - -Then you can use any shortcuts to its properties that you import from the -'chrome' module ('Cc', 'Ci', 'Cm', 'Cr', and 'Cu' for the 'classes', -'interfaces', 'manager', 'results', and 'utils' properties, respectively. And -`components` for `Components` object itself). -""" % { "fn": fn, "needs": ",".join(sorted(old_chrome)), - "lines": "\n".join([" %3d: %s" % (lineno,line) - for (lineno, line) in old_chrome_lines]), - } - problems = True - return problems - -def scan_module(fn, lines, stderr=sys.stderr): - filename = os.path.basename(fn) - requires, locations = scan_requirements_with_grep(fn, lines) - if filename == "cuddlefish.js": - # this is the loader: don't scan for chrome - problems = False - else: - problems = scan_for_bad_chrome(fn, lines, stderr) - return requires, problems, locations - - - -if __name__ == '__main__': - for fn in sys.argv[1:]: - requires, problems, locations = scan_module(fn, open(fn).readlines()) - print - print "---", fn - if problems: - print "PROBLEMS" - sys.exit(1) - print "requires: %s" % (",".join(sorted(requires.keys()))) - print "locations: %s" % locations diff --git a/addon-sdk/source/python-lib/cuddlefish/mobile-utils/bootstrap.js b/addon-sdk/source/python-lib/cuddlefish/mobile-utils/bootstrap.js deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/mobile-utils/bootstrap.js +++ /dev/null @@ -1,46 +0,0 @@ -/* 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/. */ -"use strict"; - -Cu.import("resource://gre/modules/Services.jsm"); - -var { log } = console; - -function startup(data, reason) { - // This code allow to make all stdIO work - try { - Cu.import("resource://gre/modules/ctypes.jsm"); - let libdvm = ctypes.open("libdvm.so"); - let dvmStdioConverterStartup; - // Starting with Android ICS, dalvik uses C++. - // So that the symbol isn't a simple C one - try { - dvmStdioConverterStartup = libdvm.declare("_Z24dvmStdioConverterStartupv", ctypes.default_abi, ctypes.bool); - } - catch(e) { - // Otherwise, before ICS, it was a pure C library - dvmStdioConverterStartup = libdvm.declare("dvmStdioConverterStartup", ctypes.default_abi, ctypes.void_t); - } - dvmStdioConverterStartup(); - log("MU: console redirected to adb logcat."); - } catch(e) { - Cu.reportError("MU: unable to execute jsctype hack: "+e); - } - - try { - let QuitObserver = { - observe: function (aSubject, aTopic, aData) { - Services.obs.removeObserver(QuitObserver, "quit-application"); - dump("MU: APPLICATION-QUIT\n"); - } - }; - Services.obs.addObserver(QuitObserver, "quit-application"); - log("MU: ready to watch firefox exit."); - } catch(e) { - log("MU: unable to register quit-application observer: " + e); - } -} - -function install() {} -function shutdown() {} diff --git a/addon-sdk/source/python-lib/cuddlefish/mobile-utils/install.rdf b/addon-sdk/source/python-lib/cuddlefish/mobile-utils/install.rdf deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/mobile-utils/install.rdf +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - mobile-utils@mozilla.com - 1.0 - 2 - true - - - - - {a23983c0-fd0e-11dc-95ff-0800200c9a66} - 1 - * - - - - - - - {aa3c5121-dab2-40e2-81ca-7ea25febc110} - 1 - * - - - - - Mobile Addon-SDK utility addon - Allow better integration with cfx tool. - Mozilla Corporation - - - diff --git a/addon-sdk/source/python-lib/cuddlefish/packaging.py b/addon-sdk/source/python-lib/cuddlefish/packaging.py deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/packaging.py +++ /dev/null @@ -1,463 +0,0 @@ -# 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/. - -import os -import sys -import re -import copy - -import simplejson as json -from cuddlefish.bunch import Bunch - -MANIFEST_NAME = 'package.json' -DEFAULT_LOADER = 'addon-sdk' - -# Is different from root_dir when running tests -env_root = os.environ.get('CUDDLEFISH_ROOT') - -DEFAULT_PROGRAM_MODULE = 'main' - -DEFAULT_ICON = 'icon.png' -DEFAULT_ICON64 = 'icon64.png' - -METADATA_PROPS = ['name', 'description', 'keywords', 'author', 'version', - 'developers', 'translators', 'contributors', 'license', 'homepage', - 'icon', 'icon64', 'main', 'directories', 'permissions', 'preferences'] - -RESOURCE_HOSTNAME_RE = re.compile(r'^[a-z0-9_\-]+$') - -class Error(Exception): - pass - -class MalformedPackageError(Error): - pass - -class MalformedJsonFileError(Error): - pass - -class DuplicatePackageError(Error): - pass - -class PackageNotFoundError(Error): - def __init__(self, missing_package, reason): - self.missing_package = missing_package - self.reason = reason - def __str__(self): - return "%s (%s)" % (self.missing_package, self.reason) - -class BadChromeMarkerError(Error): - pass - -def validate_resource_hostname(name): - """ - Validates the given hostname for a resource: URI. - - For more information, see: - - https://bugzilla.mozilla.org/show_bug.cgi?id=566812#c13 - - Examples: - - >>> validate_resource_hostname('blarg') - - >>> validate_resource_hostname('bl arg') - Traceback (most recent call last): - ... - ValueError: Error: the name of your package contains an invalid character. - Package names can contain only lower-case letters, numbers, underscores, and dashes. - Current package name: bl arg - - >>> validate_resource_hostname('BLARG') - Traceback (most recent call last): - ... - ValueError: Error: the name of your package contains upper-case letters. - Package names can contain only lower-case letters, numbers, underscores, and dashes. - Current package name: BLARG - - >>> validate_resource_hostname('foo@bar') - Traceback (most recent call last): - ... - ValueError: Error: the name of your package contains an invalid character. - Package names can contain only lower-case letters, numbers, underscores, and dashes. - Current package name: foo@bar - """ - - # See https://bugzilla.mozilla.org/show_bug.cgi?id=568131 for details. - if not name.lower() == name: - raise ValueError("""Error: the name of your package contains upper-case letters. -Package names can contain only lower-case letters, numbers, underscores, and dashes. -Current package name: %s""" % name) - - if not RESOURCE_HOSTNAME_RE.match(name): - raise ValueError("""Error: the name of your package contains an invalid character. -Package names can contain only lower-case letters, numbers, underscores, and dashes. -Current package name: %s""" % name) - -def find_packages_with_module(pkg_cfg, name): - # TODO: Make this support more than just top-level modules. - filename = "%s.js" % name - packages = [] - for cfg in pkg_cfg.packages.itervalues(): - if 'lib' in cfg: - matches = [dirname for dirname in resolve_dirs(cfg, cfg.lib) - if os.path.exists(os.path.join(dirname, filename))] - if matches: - packages.append(cfg.name) - return packages - -def resolve_dirs(pkg_cfg, dirnames): - for dirname in dirnames: - yield resolve_dir(pkg_cfg, dirname) - -def resolve_dir(pkg_cfg, dirname): - return os.path.join(pkg_cfg.root_dir, dirname) - -def validate_permissions(perms): - if (perms.get('cross-domain-content') and - not isinstance(perms.get('cross-domain-content'), list)): - raise ValueError("Error: `cross-domain-content` permissions in \ - package.json file must be an array of strings:\n %s" % perms) - -def get_metadata(pkg_cfg, deps): - metadata = Bunch() - for pkg_name in deps: - cfg = pkg_cfg.packages[pkg_name] - metadata[pkg_name] = Bunch() - for prop in METADATA_PROPS: - if cfg.get(prop): - if prop == 'permissions': - validate_permissions(cfg[prop]) - metadata[pkg_name][prop] = cfg[prop] - return metadata - -def set_section_dir(base_json, name, base_path, dirnames, allow_root=False): - resolved = compute_section_dir(base_json, base_path, dirnames, allow_root) - if resolved: - base_json[name] = os.path.abspath(resolved) - -def compute_section_dir(base_json, base_path, dirnames, allow_root): - # PACKAGE_JSON.lib is highest priority - # then PACKAGE_JSON.directories.lib - # then lib/ (if it exists) - # then . (but only if allow_root=True) - for dirname in dirnames: - if base_json.get(dirname): - return os.path.join(base_path, base_json[dirname]) - if "directories" in base_json: - for dirname in dirnames: - if dirname in base_json.directories: - return os.path.join(base_path, base_json.directories[dirname]) - for dirname in dirnames: - if os.path.isdir(os.path.join(base_path, dirname)): - return os.path.join(base_path, dirname) - if allow_root: - return os.path.abspath(base_path) - return None - -def normalize_string_or_array(base_json, key): - if base_json.get(key): - if isinstance(base_json[key], basestring): - base_json[key] = [base_json[key]] - -def load_json_file(path): - data = open(path, 'r').read() - try: - return Bunch(json.loads(data)) - except ValueError, e: - raise MalformedJsonFileError('%s when reading "%s"' % (str(e), - path)) - -def get_config_in_dir(path): - package_json = os.path.join(path, MANIFEST_NAME) - if not (os.path.exists(package_json) and - os.path.isfile(package_json)): - raise MalformedPackageError('%s not found in "%s"' % (MANIFEST_NAME, - path)) - base_json = load_json_file(package_json) - - if 'name' not in base_json: - base_json.name = os.path.basename(path) - - # later processing steps will expect to see the following keys in the - # base_json that we return: - # - # name: name of the package - # lib: list of directories with .js files - # test: list of directories with test-*.js files - # doc: list of directories with documentation .md files - # data: list of directories with bundled arbitrary data files - # packages: ? - - if (not base_json.get('tests') and - os.path.isdir(os.path.join(path, 'test'))): - base_json['tests'] = 'test' - - set_section_dir(base_json, 'lib', path, ['lib'], True) - set_section_dir(base_json, 'tests', path, ['test', 'tests'], False) - set_section_dir(base_json, 'doc', path, ['doc', 'docs']) - set_section_dir(base_json, 'data', path, ['data']) - set_section_dir(base_json, 'packages', path, ['packages']) - set_section_dir(base_json, 'locale', path, ['locale']) - - if (not base_json.get('icon') and - os.path.isfile(os.path.join(path, DEFAULT_ICON))): - base_json['icon'] = DEFAULT_ICON - - if (not base_json.get('icon64') and - os.path.isfile(os.path.join(path, DEFAULT_ICON64))): - base_json['icon64'] = DEFAULT_ICON64 - - for key in ['lib', 'tests', 'dependencies', 'packages']: - # TODO: lib/tests can be an array?? consider interaction with - # compute_section_dir above - normalize_string_or_array(base_json, key) - - if 'main' not in base_json and 'lib' in base_json: - for dirname in base_json['lib']: - program = os.path.join(path, dirname, - '%s.js' % DEFAULT_PROGRAM_MODULE) - if os.path.exists(program): - base_json['main'] = DEFAULT_PROGRAM_MODULE - break - - base_json.root_dir = path - - if "dependencies" in base_json: - deps = base_json["dependencies"] - deps = [x for x in deps if x not in ["addon-kit", "api-utils"]] - deps.append("addon-sdk") - base_json["dependencies"] = deps - - return base_json - -def _is_same_file(a, b): - if hasattr(os.path, 'samefile'): - return os.path.samefile(a, b) - return a == b - -def build_config(root_dir, target_cfg, packagepath=[]): - dirs_to_scan = [env_root] # root is addon-sdk dir, diff from root_dir in tests - - def add_packages_from_config(pkgconfig): - if 'packages' in pkgconfig: - for package_dir in resolve_dirs(pkgconfig, pkgconfig.packages): - dirs_to_scan.append(package_dir) - - add_packages_from_config(target_cfg) - - packages_dir = os.path.join(root_dir, 'packages') - if os.path.exists(packages_dir) and os.path.isdir(packages_dir): - dirs_to_scan.append(packages_dir) - dirs_to_scan.extend(packagepath) - - packages = Bunch({target_cfg.name: target_cfg}) - - while dirs_to_scan: - packages_dir = dirs_to_scan.pop() - if os.path.exists(os.path.join(packages_dir, "package.json")): - package_paths = [packages_dir] - else: - package_paths = [os.path.join(packages_dir, dirname) - for dirname in os.listdir(packages_dir) - if not dirname.startswith('.')] - package_paths = [dirname for dirname in package_paths - if os.path.isdir(dirname)] - - for path in package_paths: - pkgconfig = get_config_in_dir(path) - if pkgconfig.name in packages: - otherpkg = packages[pkgconfig.name] - if not _is_same_file(otherpkg.root_dir, path): - raise DuplicatePackageError(path, otherpkg.root_dir) - else: - packages[pkgconfig.name] = pkgconfig - add_packages_from_config(pkgconfig) - - return Bunch(packages=packages) - -def get_deps_for_targets(pkg_cfg, targets): - visited = [] - deps_left = [[dep, None] for dep in list(targets)] - - while deps_left: - [dep, required_by] = deps_left.pop() - if dep not in visited: - visited.append(dep) - if dep not in pkg_cfg.packages: - required_reason = ("required by '%s'" % (required_by)) \ - if required_by is not None \ - else "specified as target" - raise PackageNotFoundError(dep, required_reason) - dep_cfg = pkg_cfg.packages[dep] - deps_left.extend([[i, dep] for i in dep_cfg.get('dependencies', [])]) - deps_left.extend([[i, dep] for i in dep_cfg.get('extra_dependencies', [])]) - - return visited - -def generate_build_for_target(pkg_cfg, target, deps, - include_tests=True, - include_dep_tests=False, - is_running_tests=False, - default_loader=DEFAULT_LOADER): - - build = Bunch(# Contains section directories for all packages: - packages=Bunch(), - locale=Bunch() - ) - - def add_section_to_build(cfg, section, is_code=False, - is_data=False): - if section in cfg: - dirnames = cfg[section] - if isinstance(dirnames, basestring): - # This is just for internal consistency within this - # function, it has nothing to do w/ a non-canonical - # configuration dict. - dirnames = [dirnames] - for dirname in resolve_dirs(cfg, dirnames): - # ensure that package name is valid - try: - validate_resource_hostname(cfg.name) - except ValueError, err: - print err - sys.exit(1) - # ensure that this package has an entry - if not cfg.name in build.packages: - build.packages[cfg.name] = Bunch() - # detect duplicated sections - if section in build.packages[cfg.name]: - raise KeyError("package's section already defined", - cfg.name, section) - # Register this section (lib, data, tests) - build.packages[cfg.name][section] = dirname - - def add_locale_to_build(cfg): - # Bug 730776: Ignore locales for addon-kit, that are only for unit tests - if not is_running_tests and cfg.name == "addon-sdk": - return - - path = resolve_dir(cfg, cfg['locale']) - files = os.listdir(path) - for filename in files: - fullpath = os.path.join(path, filename) - if os.path.isfile(fullpath) and filename.endswith('.properties'): - language = filename[:-len('.properties')] - - from property_parser import parse_file, MalformedLocaleFileError - try: - content = parse_file(fullpath) - except MalformedLocaleFileError, msg: - print msg[0] - sys.exit(1) - - # Merge current locales into global locale hashtable. - # Locale files only contains one big JSON object - # that act as an hastable of: - # "keys to translate" => "translated keys" - if language in build.locale: - merge = (build.locale[language].items() + - content.items()) - build.locale[language] = Bunch(merge) - else: - build.locale[language] = content - - def add_dep_to_build(dep): - dep_cfg = pkg_cfg.packages[dep] - add_section_to_build(dep_cfg, "lib", is_code=True) - add_section_to_build(dep_cfg, "data", is_data=True) - if include_tests and include_dep_tests: - add_section_to_build(dep_cfg, "tests", is_code=True) - if 'locale' in dep_cfg: - add_locale_to_build(dep_cfg) - if ("loader" in dep_cfg) and ("loader" not in build): - build.loader = "%s/%s" % (dep, - dep_cfg.loader) - - target_cfg = pkg_cfg.packages[target] - - if include_tests and not include_dep_tests: - add_section_to_build(target_cfg, "tests", is_code=True) - - for dep in deps: - add_dep_to_build(dep) - - if 'loader' not in build: - add_dep_to_build(DEFAULT_LOADER) - - if 'icon' in target_cfg: - build['icon'] = os.path.join(target_cfg.root_dir, target_cfg.icon) - del target_cfg['icon'] - - if 'icon64' in target_cfg: - build['icon64'] = os.path.join(target_cfg.root_dir, target_cfg.icon64) - del target_cfg['icon64'] - - if 'id' in target_cfg: - # NOTE: logic duplicated from buildJID() - jid = target_cfg['id'] - if not ('@' in jid or jid.startswith('{')): - jid += '@jetpack' - build['preferencesBranch'] = jid - - if 'preferences-branch' in target_cfg: - build['preferencesBranch'] = target_cfg['preferences-branch'] - - return build - -def _get_files_in_dir(path): - data = {} - files = os.listdir(path) - for filename in files: - fullpath = os.path.join(path, filename) - if os.path.isdir(fullpath): - data[filename] = _get_files_in_dir(fullpath) - else: - try: - info = os.stat(fullpath) - data[filename] = ("file", dict(size=info.st_size)) - except OSError: - pass - return ("directory", data) - -def build_pkg_index(pkg_cfg): - pkg_cfg = copy.deepcopy(pkg_cfg) - for pkg in pkg_cfg.packages: - root_dir = pkg_cfg.packages[pkg].root_dir - files = _get_files_in_dir(root_dir) - pkg_cfg.packages[pkg].files = files - try: - readme = open(root_dir + '/README.md').read() - pkg_cfg.packages[pkg].readme = readme - except IOError: - pass - del pkg_cfg.packages[pkg].root_dir - return pkg_cfg.packages - -def build_pkg_cfg(root): - pkg_cfg = build_config(root, Bunch(name='dummy')) - del pkg_cfg.packages['dummy'] - return pkg_cfg - -def call_plugins(pkg_cfg, deps): - for dep in deps: - dep_cfg = pkg_cfg.packages[dep] - dirnames = dep_cfg.get('python-lib', []) - for dirname in resolve_dirs(dep_cfg, dirnames): - sys.path.append(dirname) - module_names = dep_cfg.get('python-plugins', []) - for module_name in module_names: - module = __import__(module_name) - module.init(root_dir=dep_cfg.root_dir) - -def call_cmdline_tool(env_root, pkg_name): - pkg_cfg = build_config(env_root, Bunch(name='dummy')) - if pkg_name not in pkg_cfg.packages: - print "This tool requires the '%s' package." % pkg_name - sys.exit(1) - cfg = pkg_cfg.packages[pkg_name] - for dirname in resolve_dirs(cfg, cfg['python-lib']): - sys.path.append(dirname) - module_name = cfg.get('python-cmdline-tool') - module = __import__(module_name) - module.run() diff --git a/addon-sdk/source/python-lib/cuddlefish/preflight.py b/addon-sdk/source/python-lib/cuddlefish/preflight.py deleted file mode 100755 --- a/addon-sdk/source/python-lib/cuddlefish/preflight.py +++ /dev/null @@ -1,77 +0,0 @@ -# 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/. - -import os, sys -import base64 -import simplejson as json - -def create_jid(): - """Return 'jid1-XYZ', where 'XYZ' is a randomly-generated string. (in the - previous jid0- series, the string securely identified a specific public - key). To get a suitable add-on ID, append '@jetpack' to this string. - """ - # per https://developer.mozilla.org/en/Install_Manifests#id all XPI id - # values must either be in the form of a 128-bit GUID (crazy braces - # and all) or in the form of an email address (crazy @ and all). - # Firefox will refuse to install an add-on with an id that doesn't - # match one of these forms. The actual regexp is at: - # http://mxr.mozilla.org/mozilla-central/source/toolkit/mozapps/extensions/internal/XPIProvider.jsm#130 - # So the JID needs an @-suffix, and the only legal punctuation is - # "-._". So we start with a base64 encoding, and replace the - # punctuation (+/) with letters (AB), losing a few bits of integrity. - - # even better: windows has a maximum path length limitation of 256 - # characters: - # http://msdn.microsoft.com/en-us/library/aa365247%28VS.85%29.aspx - # (unless all paths are prefixed with "\\?\", I kid you not). The - # typical install will put add-on code in a directory like: - # C:\Documents and Settings\\Application Data\Mozilla\Firefox\Profiles\232353483.default\extensions\$JID\... - # (which is 108 chars long without the $JID). - # Then the unpacked XPI contains packaged resources like: - # resources/$JID-api-utils-lib/main.js (35 chars plus the $JID) - # - # We create a random 80 bit string, base64 encode that (with - # AB instead of +/ to be path-safe), then bundle it into - # "jid1-XYZ@jetpack". This gives us 27 characters. The resulting - # main.js will have a path length of 211 characters, leaving us 45 - # characters of margin. - # - # 80 bits is enough to generate one billion JIDs and still maintain lower - # than a one-in-a-million chance of accidental collision. (1e9 JIDs is 30 - # bits, square for the "birthday-paradox" to get 60 bits, add 20 bits for - # the one-in-a-million margin to get 80 bits) - - # if length were no issue, we'd prefer to use this: - h = os.urandom(80/8) - s = base64.b64encode(h, "AB").strip("=") - jid = "jid1-" + s - return jid - -def preflight_config(target_cfg, filename, stderr=sys.stderr): - modified = False - config = json.load(open(filename, 'r')) - - if "id" not in config: - print >>stderr, ("No 'id' in package.json: creating a new ID for you.") - jid = create_jid() - config["id"] = jid - modified = True - - if modified: - i = 0 - backup = filename + ".backup" - while os.path.exists(backup): - if i > 1000: - raise ValueError("I'm having problems finding a good name" - " for the backup file. Please move %s out" - " of the way and try again." - % (filename + ".backup")) - backup = filename + ".backup-%d" % i - i += 1 - os.rename(filename, backup) - new_json = json.dumps(config, indent=4) - open(filename, 'w').write(new_json+"\n") - return False, True - - return True, False diff --git a/addon-sdk/source/python-lib/cuddlefish/prefs.py b/addon-sdk/source/python-lib/cuddlefish/prefs.py deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/prefs.py +++ /dev/null @@ -1,241 +0,0 @@ -# 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/. - -DEFAULT_COMMON_PREFS = { - # allow debug output via dump to be printed to the system console - # (setting it here just in case, even though PlainTextConsole also - # sets this preference) - 'browser.dom.window.dump.enabled': True, - # warn about possibly incorrect code - 'javascript.options.showInConsole': True, - - # Allow remote connections to the debugger - 'devtools.debugger.remote-enabled' : True, - - 'extensions.sdk.console.logLevel': 'info', - - 'extensions.checkCompatibility.nightly' : False, - - # Disable extension updates and notifications. - 'extensions.update.enabled' : False, - 'lightweightThemes.update.enabled' : False, - 'extensions.update.notifyUser' : False, - - # From: - # https://hg.mozilla.org/mozilla-central/file/1dd81c324ac7/build/automation.py.in#l372 - # Only load extensions from the application and user profile. - # AddonManager.SCOPE_PROFILE + AddonManager.SCOPE_APPLICATION - 'extensions.enabledScopes' : 5, - # Disable metadata caching for installed add-ons by default - 'extensions.getAddons.cache.enabled' : False, - # Disable intalling any distribution add-ons - 'extensions.installDistroAddons' : False, - # Allow installing extensions dropped into the profile folder - 'extensions.autoDisableScopes' : 10, - - # shut up some warnings on `about:` page - 'app.releaseNotesURL': 'http://localhost/app-dummy/', - 'app.vendorURL': 'http://localhost/app-dummy/', -} - -DEFAULT_NO_CONNECTIONS_PREFS = { - 'toolkit.telemetry.enabled': False, - 'toolkit.telemetry.server': 'https://localhost/telemetry-dummy/', - 'app.update.auto' : False, - 'app.update.url': 'http://localhost/app-dummy/update', - # Make sure GMPInstallManager won't hit the network. - 'media.gmp-gmpopenh264.autoupdate' : False, - 'media.gmp-manager.cert.checkAttributes' : False, - 'media.gmp-manager.cert.requireBuiltIn' : False, - 'media.gmp-manager.url' : 'http://localhost/media-dummy/gmpmanager', - 'media.gmp-manager.url.override': 'http://localhost/dummy-gmp-manager.xml', - 'media.gmp-manager.updateEnabled': False, - 'browser.aboutHomeSnippets.updateUrl': 'https://localhost/snippet-dummy', - 'browser.newtab.url' : 'about:blank', - 'browser.search.update': False, - 'browser.search.suggest.enabled' : False, - - # Disable all Safe Browsing lists - 'browser.safebrowsing.downloads.remote.url': 'http://localhost/safebrowsing-dummy/downloads', - 'browser.safebrowsing.malware.enabled' : False, - 'browser.safebrowsing.phishing.enabled' : False, - 'browser.safebrowsing.blockedURIs.enabled' : False, - 'browser.safebrowsing.passwords.enabled' : False, - 'browser.safebrowsing.provider.google.updateURL': 'http://localhost/safebrowsing-dummy/update', - 'browser.safebrowsing.provider.google.gethashURL': 'http://localhost/safebrowsing-dummy/gethash', - 'browser.safebrowsing.provider.google4.updateURL': 'http://localhost/safebrowsing4-dummy/update', - 'browser.safebrowsing.provider.google4.gethashURL': 'http://localhost/safebrowsing4-dummy/gethash', - 'browser.safebrowsing.provider.mozilla.gethashURL': 'http://localhost/safebrowsing-dummy/gethash', - 'browser.safebrowsing.provider.mozilla.updateURL': 'http://localhost/safebrowsing-dummy/update', - 'privacy.trackingprotection.annotate_channels': False, - 'privacy.trackingprotection.enabled': False, - 'privacy.trackingprotection.pbmode.enabled': False, - - # Disable app update - 'app.update.enabled' : False, - 'app.update.staging.enabled': False, - - # Disable about:newtab content fetch - 'browser.newtabpage.directory.source': 'data:application/json,{"jetpack":1}', - - # Point update checks to a nonexistent local URL for fast failures. - 'extensions.update.url' : 'http://localhost/extensions-dummy/updateURL', - 'extensions.update.background.url': 'http://localhost/extensions-dummy/updateBackgroundURL', - 'extensions.blocklist.url' : 'http://localhost/extensions-dummy/blocklistURL', - # Make sure opening about:addons won't hit the network. - 'extensions.webservice.discoverURL' : 'http://localhost/extensions-dummy/discoveryURL', - 'extensions.getAddons.maxResults': 0, - - # Disable webapp updates. Yes, it is supposed to be an integer. - 'browser.webapps.checkForUpdates': 0, - - # Location services - 'geo.wifi.uri': 'http://localhost/location-dummy/locationURL', - 'browser.search.geoip.url': 'http://localhost/location-dummy/locationURL', - - # Tell the search service we are running in the US. This also has the - # desired side-effect of preventing our geoip lookup. - 'browser.search.isUS' : True, - 'browser.search.countryCode' : 'US', - - 'geo.wifi.uri' : 'http://localhost/extensions-dummy/geowifiURL', - 'geo.wifi.scan' : False, - - # We don't want to hit the real Firefox Accounts server for tests. We don't - # actually need a functioning FxA server, so just set it to something that - # resolves and accepts requests, even if they all fail. - 'identity.fxaccounts.auth.uri': 'http://localhost/fxa-dummy/' -} - -DEFAULT_FENNEC_PREFS = { - 'browser.console.showInPanel': True, - 'browser.firstrun.show.uidiscovery': False -} - -# When launching a temporary new Firefox profile, use these preferences. -DEFAULT_FIREFOX_PREFS = { - 'browser.startup.homepage' : 'about:blank', - 'startup.homepage_welcome_url' : 'about:blank', - 'devtools.browsertoolbox.panel': 'jsdebugger', - 'devtools.chrome.enabled' : True, - - # Point the url-classifier to a nonexistent local URL for fast failures. - 'browser.safebrowsing.downloads.remote.url': 'http://localhost/safebrowsing-dummy/downloads', - 'browser.safebrowsing.provider.google.gethashURL' : 'http://localhost/safebrowsing-dummy/gethash', - 'browser.safebrowsing.provider.google.updateURL' : 'http://localhost/safebrowsing-dummy/update', - 'browser.safebrowsing.provider.google4.gethashURL' : 'http://localhost/safebrowsing4-dummy/gethash', - 'browser.safebrowsing.provider.google4.updateURL' : 'http://localhost/safebrowsing4-dummy/update', - 'browser.safebrowsing.provider.mozilla.gethashURL': 'http://localhost/safebrowsing-dummy/gethash', - 'browser.safebrowsing.provider.mozilla.updateURL': 'http://localhost/safebrowsing-dummy/update', -} - -# When launching a temporary new Thunderbird profile, use these preferences. -# Note that these were taken from: -# http://dxr.mozilla.org/comm-central/source/mail/test/mozmill/runtest.py -DEFAULT_THUNDERBIRD_PREFS = { - # say no to slow script warnings - 'dom.max_chrome_script_run_time': 200, - 'dom.max_script_run_time': 0, - # do not ask about being the default mail client - 'mail.shell.checkDefaultClient': False, - # disable non-gloda indexing daemons - 'mail.winsearch.enable': False, - 'mail.winsearch.firstRunDone': True, - 'mail.spotlight.enable': False, - 'mail.spotlight.firstRunDone': True, - # disable address books for undisclosed reasons - 'ldap_2.servers.osx.position': 0, - 'ldap_2.servers.oe.position': 0, - # disable the first use junk dialog - 'mailnews.ui.junk.firstuse': False, - # other unknown voodoo - # -- dummied up local accounts to stop the account wizard - 'mail.account.account1.server' : "server1", - 'mail.account.account2.identities' : "id1", - 'mail.account.account2.server' : "server2", - 'mail.accountmanager.accounts' : "account1,account2", - 'mail.accountmanager.defaultaccount' : "account2", - 'mail.accountmanager.localfoldersserver' : "server1", - 'mail.identity.id1.fullName' : "Tinderbox", - 'mail.identity.id1.smtpServer' : "smtp1", - 'mail.identity.id1.useremail' : "tinderbox@invalid.com", - 'mail.identity.id1.valid' : True, - 'mail.root.none-rel' : "[ProfD]Mail", - 'mail.root.pop3-rel' : "[ProfD]Mail", - 'mail.server.server1.directory-rel' : "[ProfD]Mail/Local Folders", - 'mail.server.server1.hostname' : "Local Folders", - 'mail.server.server1.name' : "Local Folders", - 'mail.server.server1.type' : "none", - 'mail.server.server1.userName' : "nobody", - 'mail.server.server2.check_new_mail' : False, - 'mail.server.server2.directory-rel' : "[ProfD]Mail/tinderbox", - 'mail.server.server2.download_on_biff' : True, - 'mail.server.server2.hostname' : "tinderbox", - 'mail.server.server2.login_at_startup' : False, - 'mail.server.server2.name' : "tinderbox@invalid.com", - 'mail.server.server2.type' : "pop3", - 'mail.server.server2.userName' : "tinderbox", - 'mail.smtp.defaultserver' : "smtp1", - 'mail.smtpserver.smtp1.hostname' : "tinderbox", - 'mail.smtpserver.smtp1.username' : "tinderbox", - 'mail.smtpservers' : "smtp1", - 'mail.startup.enabledMailCheckOnce' : True, - 'mailnews.start_page_override.mstone' : "ignore", -} - -DEFAULT_TEST_PREFS = { - 'browser.console.showInPanel': True, - 'browser.startup.page': 0, - 'browser.firstrun.show.localepicker': False, - 'browser.firstrun.show.uidiscovery': False, - 'browser.ui.layout.tablet': 0, - 'dom.disable_open_during_load': False, - 'dom.experimental_forms': True, - 'dom.forms.number': True, - 'dom.forms.color': True, - 'dom.max_script_run_time': 0, - 'hangmonitor.timeout': 0, - 'dom.max_chrome_script_run_time': 0, - 'dom.popup_maximum': -1, - 'dom.send_after_paint_to_content': True, - 'dom.successive_dialog_time_limit': 0, - 'browser.shell.checkDefaultBrowser': False, - 'shell.checkDefaultClient': False, - 'browser.warnOnQuit': False, - 'accessibility.typeaheadfind.autostart': False, - 'browser.EULA.override': True, - 'gfx.color_management.force_srgb': True, - 'network.manage-offline-status': False, - # Disable speculative connections so they aren't reported as leaking when they're hanging around. - 'network.http.speculative-parallel-limit': 0, - 'test.mousescroll': True, - # Need to client auth test be w/o any dialogs - 'security.default_personal_cert': 'Select Automatically', - 'network.http.prompt-temp-redirect': False, - 'security.warn_viewing_mixed': False, - 'extensions.defaultProviders.enabled': True, - 'datareporting.policy.dataSubmissionPolicyBypassNotification': True, - 'layout.css.report_errors': True, - 'layout.spammy_warnings.enabled': False, - # Always use network provider for geolocation tests - # so we bypass the OSX dialog raised by the corelocation provider - 'geo.provider.testing': True, - # Background thumbnails in particular cause grief, and disabling thumbnails - # in general can't hurt - we re-enable them when tests need them. - 'browser.pagethumbnails.capturing_disabled': True, - # Indicate that the download panel has been shown once so that whichever - # download test runs first doesn't show the popup inconsistently. - 'browser.download.panel.shown': True, - # Assume the about:newtab page's intro panels have been shown to not depend on - # which test runs first and happens to open about:newtab - 'browser.newtabpage.introShown': True, - # Disable useragent updates. - 'general.useragent.updates.enabled': False, - 'media.eme.enabled': True, - # Don't forcibly kill content processes after a timeout - 'dom.ipc.tabs.shutdownTimeoutSecs': 0, - 'general.useragent.locale': "en-US", - 'intl.locale.matchOS': "en-US", - 'dom.indexedDB.experimental': True -} diff --git a/addon-sdk/source/python-lib/cuddlefish/property_parser.py b/addon-sdk/source/python-lib/cuddlefish/property_parser.py deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/property_parser.py +++ /dev/null @@ -1,111 +0,0 @@ -# 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/. - -import re -import codecs - -class MalformedLocaleFileError(Exception): - pass - -def parse_file(path): - return parse(read_file(path), path) - -def read_file(path): - try: - return codecs.open( path, "r", "utf-8" ).readlines() - except UnicodeDecodeError, e: - raise MalformedLocaleFileError( - 'Following locale file is not a valid ' + - 'UTF-8 file: %s\n%s"' % (path, str(e))) - -COMMENT = re.compile(r'\s*#') -EMPTY = re.compile(r'^\s+$') -KEYVALUE = re.compile(r"\s*([^=:]+)(=|:)\s*(.*)") - -def parse(lines, path=None): - lines = iter(lines) - lineNo = 1 - pairs = dict() - for line in lines: - if COMMENT.match(line) or EMPTY.match(line) or len(line) == 0: - continue - m = KEYVALUE.match(line) - if not m: - raise MalformedLocaleFileError( - 'Following locale file is not a valid .properties file: %s\n' - 'Line %d is incorrect:\n%s' % (path, lineNo, line)) - - # All spaces are strip. Spaces at the beginning are stripped - # by the regular expression. We have to strip spaces at the end. - key = m.group(1).rstrip() - val = m.group(3).rstrip() - val = val.encode('raw-unicode-escape').decode('raw-unicode-escape') - - # `key` can be empty when key is only made of spaces - if not key: - raise MalformedLocaleFileError( - 'Following locale file is not a valid .properties file: %s\n' - 'Key is invalid on line %d is incorrect:\n%s' % - (path, lineNo, line)) - - # Multiline value: keep reading lines, while lines end with backslash - # and strip spaces at the beginning of lines except the last line - # that doesn't end up with backslash, we strip all spaces for this one. - if val.endswith("\\"): - val = val[:-1] - try: - # remove spaces before/after and especially the \n at EOL - line = lines.next().strip() - while line.endswith("\\"): - val += line[:-1].lstrip() - line = lines.next() - lineNo += 1 - val += line.strip() - except StopIteration: - raise MalformedLocaleFileError( - 'Following locale file is not a valid .properties file: %s\n' - 'Unexpected EOF in multiline sequence at line %d:\n%s' % - (path, lineNo, line)) - # Save this new pair - pairs[key] = val - lineNo += 1 - - normalize_plural(path, pairs) - return pairs - -# Plural forms in properties files are defined like this: -# key = other form -# key[one] = one form -# key[...] = ... -# Parse them and merge each key into one object containing all forms: -# key: { -# other: "other form", -# one: "one form", -# ...: ... -# } -PLURAL_FORM = re.compile(r'^(.*)\[(zero|one|two|few|many|other)\]$') -def normalize_plural(path, pairs): - for key in list(pairs.keys()): - m = PLURAL_FORM.match(key) - if not m: - continue - main_key = m.group(1) - plural_form = m.group(2) - # Allows not specifying a generic key (i.e a key without [form]) - if not main_key in pairs: - pairs[main_key] = {} - # Ensure that we always have the [other] form - if not main_key + "[other]" in pairs: - raise MalformedLocaleFileError( - 'Following locale file is not a valid UTF-8 file: %s\n' - 'This plural form doesn\'t have a matching `%s[other]` form:\n' - '%s\n' - 'You have to defined following key:\n%s' - % (path, main_key, key, main_key)) - # convert generic form into an object if it is still a string - if isinstance(pairs[main_key], unicode): - pairs[main_key] = {"other": pairs[main_key]} - # then, add this new plural form - pairs[main_key][plural_form] = pairs[key] - del pairs[key] diff --git a/addon-sdk/source/python-lib/cuddlefish/rdf.py b/addon-sdk/source/python-lib/cuddlefish/rdf.py deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/rdf.py +++ /dev/null @@ -1,214 +0,0 @@ -# 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/. - -import os -import xml.dom.minidom -import StringIO - -RDF_NS = "http://www.w3.org/1999/02/22-rdf-syntax-ns#" -EM_NS = "http://www.mozilla.org/2004/em-rdf#" - -class RDF(object): - def __str__(self): - # real files have an .encoding attribute and use it when you - # write() unicode into them: they read()/write() unicode and - # put encoded bytes in the backend file. StringIO objects - # read()/write() unicode and put unicode in the backing store, - # so we must encode the output of getvalue() to get a - # bytestring. (cStringIO objects are weirder: they effectively - # have .encoding hardwired to "ascii" and put only bytes in - # the backing store, so we can't use them here). - # - # The encoding= argument to dom.writexml() merely sets the XML header's - # encoding= attribute. It still writes unencoded unicode to the output file, - # so we have to encode it for real afterwards. - # - # Also see: https://bugzilla.mozilla.org/show_bug.cgi?id=567660 - - buf = StringIO.StringIO() - self.dom.writexml(buf, encoding="utf-8") - return buf.getvalue().encode('utf-8') - -class RDFUpdate(RDF): - def __init__(self): - impl = xml.dom.minidom.getDOMImplementation() - self.dom = impl.createDocument(RDF_NS, "RDF", None) - self.dom.documentElement.setAttribute("xmlns", RDF_NS) - self.dom.documentElement.setAttribute("xmlns:em", EM_NS) - - def _make_node(self, name, value, parent): - elem = self.dom.createElement(name) - elem.appendChild(self.dom.createTextNode(value)) - parent.appendChild(elem) - return elem - - def add(self, manifest, update_link): - desc = self.dom.createElement("Description") - desc.setAttribute( - "about", - "urn:mozilla:extension:%s" % manifest.get("em:id") - ) - self.dom.documentElement.appendChild(desc) - - updates = self.dom.createElement("em:updates") - desc.appendChild(updates) - - seq = self.dom.createElement("Seq") - updates.appendChild(seq) - - li = self.dom.createElement("li") - seq.appendChild(li) - - li_desc = self.dom.createElement("Description") - li.appendChild(li_desc) - - self._make_node("em:version", manifest.get("em:version"), - li_desc) - - apps = manifest.dom.documentElement.getElementsByTagName( - "em:targetApplication" - ) - - for app in apps: - target_app = self.dom.createElement("em:targetApplication") - li_desc.appendChild(target_app) - - ta_desc = self.dom.createElement("Description") - target_app.appendChild(ta_desc) - - for name in ["em:id", "em:minVersion", "em:maxVersion"]: - elem = app.getElementsByTagName(name)[0] - self._make_node(name, elem.firstChild.nodeValue, ta_desc) - - self._make_node("em:updateLink", update_link, ta_desc) - -class RDFManifest(RDF): - def __init__(self, path): - self.dom = xml.dom.minidom.parse(path) - - def set(self, property, value): - elements = self.dom.documentElement.getElementsByTagName(property) - if not elements: - raise ValueError("Element with value not found: %s" % property) - if not elements[0].firstChild: - elements[0].appendChild(self.dom.createTextNode(value)) - else: - elements[0].firstChild.nodeValue = value - - def get(self, property, default=None): - elements = self.dom.documentElement.getElementsByTagName(property) - if not elements: - return default - return elements[0].firstChild.nodeValue - - def remove(self, property): - elements = self.dom.documentElement.getElementsByTagName(property) - if not elements: - return True - else: - for i in elements: - i.parentNode.removeChild(i); - - return True; - -def gen_manifest(template_root_dir, target_cfg, jid, - update_url=None, bootstrap=True, enable_mobile=False): - install_rdf = os.path.join(template_root_dir, "install.rdf") - manifest = RDFManifest(install_rdf) - dom = manifest.dom - - manifest.set("em:id", jid) - manifest.set("em:version", - target_cfg.get('version', '1.0')) - manifest.set("em:name", - target_cfg.get('title', target_cfg.get('fullName', target_cfg['name']))) - manifest.set("em:description", - target_cfg.get("description", "")) - manifest.set("em:creator", - target_cfg.get("author", "")) - manifest.set("em:bootstrap", str(bootstrap).lower()) - # XPIs remain packed by default, but package.json can override that. The - # RDF format accepts "true" as True, anything else as False. We expect - # booleans in the .json file, not strings. - manifest.set("em:unpack", "true" if target_cfg.get("unpack") else "false") - - if target_cfg.get('hasEmbeddedWebExtension', False): - elem = dom.createElement("em:hasEmbeddedWebExtension"); - elem.appendChild(dom.createTextNode("true")) - dom.documentElement.getElementsByTagName("Description")[0].appendChild(elem) - - for translator in target_cfg.get("translators", [ ]): - elem = dom.createElement("em:translator"); - elem.appendChild(dom.createTextNode(translator)) - dom.documentElement.getElementsByTagName("Description")[0].appendChild(elem) - - for developer in target_cfg.get("developers", [ ]): - elem = dom.createElement("em:developer"); - elem.appendChild(dom.createTextNode(developer)) - dom.documentElement.getElementsByTagName("Description")[0].appendChild(elem) - - for contributor in target_cfg.get("contributors", [ ]): - elem = dom.createElement("em:contributor"); - elem.appendChild(dom.createTextNode(contributor)) - dom.documentElement.getElementsByTagName("Description")[0].appendChild(elem) - - if update_url: - manifest.set("em:updateURL", update_url) - else: - manifest.remove("em:updateURL") - - if target_cfg.get("preferences"): - manifest.set("em:optionsType", "2") - - # workaround until bug 971249 is fixed - # https://bugzilla.mozilla.org/show_bug.cgi?id=971249 - manifest.set("em:optionsURL", "data:text/xml,") - - # workaround for workaround, for testing simple-prefs-regression - if (os.path.exists(os.path.join(template_root_dir, "options.xul"))): - manifest.remove("em:optionsURL") - else: - manifest.remove("em:optionsType") - manifest.remove("em:optionsURL") - - if enable_mobile: - target_app = dom.createElement("em:targetApplication") - dom.documentElement.getElementsByTagName("Description")[0].appendChild(target_app) - - ta_desc = dom.createElement("Description") - target_app.appendChild(ta_desc) - - elem = dom.createElement("em:id") - elem.appendChild(dom.createTextNode("{aa3c5121-dab2-40e2-81ca-7ea25febc110}")) - ta_desc.appendChild(elem) - - elem = dom.createElement("em:minVersion") - elem.appendChild(dom.createTextNode("26.0")) - ta_desc.appendChild(elem) - - elem = dom.createElement("em:maxVersion") - elem.appendChild(dom.createTextNode("30.0a1")) - ta_desc.appendChild(elem) - - if target_cfg.get("homepage"): - manifest.set("em:homepageURL", target_cfg.get("homepage")) - else: - manifest.remove("em:homepageURL") - - return manifest - -if __name__ == "__main__": - print "Running smoke test." - root = os.path.join(os.path.dirname(__file__), '../../app-extension') - manifest = gen_manifest(root, {'name': 'test extension'}, - 'fakeid', 'http://foo.com/update.rdf') - update = RDFUpdate() - update.add(manifest, "https://foo.com/foo.xpi") - exercise_str = str(manifest) + str(update) - for tagname in ["em:targetApplication", "em:version", "em:id"]: - if not len(update.dom.getElementsByTagName(tagname)): - raise Exception("tag does not exist: %s" % tagname) - if not update.dom.getElementsByTagName(tagname)[0].firstChild: - raise Exception("tag has no children: %s" % tagname) - print "Success!" diff --git a/addon-sdk/source/python-lib/cuddlefish/runner.py b/addon-sdk/source/python-lib/cuddlefish/runner.py deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/runner.py +++ /dev/null @@ -1,767 +0,0 @@ -# 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/. - -import os -import sys -import time -import tempfile -import atexit -import shlex -import subprocess -import re -import shutil - -import mozrunner -from cuddlefish.prefs import DEFAULT_COMMON_PREFS -from cuddlefish.prefs import DEFAULT_FIREFOX_PREFS -from cuddlefish.prefs import DEFAULT_THUNDERBIRD_PREFS -from cuddlefish.prefs import DEFAULT_FENNEC_PREFS -from cuddlefish.prefs import DEFAULT_NO_CONNECTIONS_PREFS -from cuddlefish.prefs import DEFAULT_TEST_PREFS - -# Used to remove noise from ADB output -CLEANUP_ADB = re.compile(r'^(I|E)/(stdout|stderr|GeckoConsole)\s*\(\s*\d+\):\s*(.*)$') -# Used to filter only messages send by `console` module -FILTER_ONLY_CONSOLE_FROM_ADB = re.compile(r'^I/(stdout|stderr)\s*\(\s*\d+\):\s*((info|warning|error|debug): .*)$') - -# Used to detect the currently running test -PARSEABLE_TEST_NAME = re.compile(r'TEST-START \| ([^\n]+)\n') - -# Maximum time we'll wait for tests to finish, in seconds. -# The purpose of this timeout is to recover from infinite loops. It should be -# longer than the amount of time any test run takes, including those on slow -# machines running slow (debug) versions of Firefox. -RUN_TIMEOUT = 5400 #1.5 hours (1.5 * 60 * 60 sec) - -# Maximum time we'll wait for tests to emit output, in seconds. -# The purpose of this timeout is to recover from hangs. It should be longer -# than the amount of time any test takes to report results. -OUTPUT_TIMEOUT = 300 #five minutes (60 * 5 sec) - -def follow_file(filename): - """ - Generator that yields the latest unread content from the given - file, or None if no new content is available. - - For example: - - >>> f = open('temp.txt', 'w') - >>> f.write('hello') - >>> f.flush() - >>> tail = follow_file('temp.txt') - >>> tail.next() - 'hello' - >>> tail.next() is None - True - >>> f.write('there') - >>> f.flush() - >>> tail.next() - 'there' - >>> f.close() - >>> os.remove('temp.txt') - """ - - last_pos = 0 - last_size = 0 - while True: - newstuff = None - if os.path.exists(filename): - size = os.stat(filename).st_size - if size > last_size: - last_size = size - f = open(filename, 'r') - f.seek(last_pos) - newstuff = f.read() - last_pos = f.tell() - f.close() - yield newstuff - -# subprocess.check_output only appeared in python2.7, so this code is taken -# from python source code for compatibility with py2.5/2.6 -class CalledProcessError(Exception): - def __init__(self, returncode, cmd, output=None): - self.returncode = returncode - self.cmd = cmd - self.output = output - def __str__(self): - return "Command '%s' returned non-zero exit status %d" % (self.cmd, self.returncode) - -def check_output(*popenargs, **kwargs): - if 'stdout' in kwargs: - raise ValueError('stdout argument not allowed, it will be overridden.') - process = subprocess.Popen(stdout=subprocess.PIPE, *popenargs, **kwargs) - output, unused_err = process.communicate() - retcode = process.poll() - if retcode: - cmd = kwargs.get("args") - if cmd is None: - cmd = popenargs[0] - raise CalledProcessError(retcode, cmd, output=output) - return output - - -class FennecProfile(mozrunner.Profile): - preferences = {} - names = ['fennec'] - -FENNEC_REMOTE_PATH = '/mnt/sdcard/jetpack-profile' - -class RemoteFennecRunner(mozrunner.Runner): - profile_class = FennecProfile - - names = ['fennec'] - - _INTENT_PREFIX = 'org.mozilla.' - - _adb_path = None - - def __init__(self, binary=None, **kwargs): - # Check that we have a binary set - if not binary: - raise ValueError("You have to define `--binary` option set to the " - "path to your ADB executable.") - # Ensure that binary refer to a valid ADB executable - output = subprocess.Popen([binary], stdout=subprocess.PIPE, - stderr=subprocess.PIPE).communicate() - output = "".join(output) - if not ("Android Debug Bridge" in output): - raise ValueError("`--binary` option should be the path to your " - "ADB executable.") - self.binary = binary - - mobile_app_name = kwargs['cmdargs'][0] - self.profile = kwargs['profile'] - self._adb_path = binary - - # This pref has to be set to `false` otherwise, we do not receive - # output of adb commands! - subprocess.call([self._adb_path, "shell", - "setprop log.redirect-stdio false"]) - - # Android apps are launched by their "intent" name, - # Automatically detect already installed firefox by using `pm` program - # or use name given as cfx `--mobile-app` argument. - intents = self.getIntentNames() - if not intents: - raise ValueError("Unable to find any Firefox " - "application on your device.") - elif mobile_app_name: - if not mobile_app_name in intents: - raise ValueError("Unable to find Firefox application " - "with intent name '%s'\n" - "Available ones are: %s" % - (mobile_app_name, ", ".join(intents))) - self._intent_name = self._INTENT_PREFIX + mobile_app_name - else: - if "firefox" in intents: - self._intent_name = self._INTENT_PREFIX + "firefox" - elif "firefox_beta" in intents: - self._intent_name = self._INTENT_PREFIX + "firefox_beta" - elif "firefox_nightly" in intents: - self._intent_name = self._INTENT_PREFIX + "firefox_nightly" - else: - self._intent_name = self._INTENT_PREFIX + intents[0] - - print "Launching mobile application with intent name " + self._intent_name - - # First try to kill firefox if it is already running - pid = self.getProcessPID(self._intent_name) - if pid != None: - print "Killing running Firefox instance ..." - subprocess.call([self._adb_path, "shell", - "am force-stop " + self._intent_name]) - time.sleep(7) - # It appears recently that the PID still exists even after - # Fennec closes, so removing this error still allows the tests - # to pass as the new Fennec instance is able to start. - # Leaving error in but commented out for now. - # - #if self.getProcessPID(self._intent_name) != None: - # raise Exception("Unable to automatically kill running Firefox" + - # " instance. Please close it manually before " + - # "executing cfx.") - - print "Pushing the addon to your device" - - # Create a clean empty profile on the sd card - subprocess.call([self._adb_path, "shell", "rm -r " + FENNEC_REMOTE_PATH]) - subprocess.call([self._adb_path, "shell", "mkdir " + FENNEC_REMOTE_PATH]) - - # Push the profile folder created by mozrunner to the device - # (we can't simply use `adb push` as it doesn't copy empty folders) - localDir = self.profile.profile - remoteDir = FENNEC_REMOTE_PATH - for root, dirs, files in os.walk(localDir, followlinks='true'): - relRoot = os.path.relpath(root, localDir) - # Note about os.path usage below: - # Local files may be using Windows `\` separators but - # remote are always `/`, so we need to convert local ones to `/` - for file in files: - localFile = os.path.join(root, file) - remoteFile = remoteDir.replace("/", os.sep) - if relRoot != ".": - remoteFile = os.path.join(remoteFile, relRoot) - remoteFile = os.path.join(remoteFile, file) - remoteFile = "/".join(remoteFile.split(os.sep)) - subprocess.Popen([self._adb_path, "push", localFile, remoteFile], - stderr=subprocess.PIPE).wait() - for dir in dirs: - targetDir = remoteDir.replace("/", os.sep) - if relRoot != ".": - targetDir = os.path.join(targetDir, relRoot) - targetDir = os.path.join(targetDir, dir) - targetDir = "/".join(targetDir.split(os.sep)) - # `-p` option is not supported on all devices! - subprocess.call([self._adb_path, "shell", "mkdir " + targetDir]) - - @property - def command(self): - """Returns the command list to run.""" - return [self._adb_path, - "shell", - "am start " + - "-a android.activity.MAIN " + - "-n " + self._intent_name + "/" + self._intent_name + ".App " + - "--es args \"-profile " + FENNEC_REMOTE_PATH + "\"" - ] - - def start(self): - subprocess.call(self.command) - - def getProcessPID(self, processName): - p = subprocess.Popen([self._adb_path, "shell", "ps"], - stdout=subprocess.PIPE, stderr=subprocess.PIPE) - line = p.stdout.readline() - while line: - columns = line.split() - pid = columns[1] - name = columns[-1] - line = p.stdout.readline() - if processName in name: - return pid - return None - - def getIntentNames(self): - p = subprocess.Popen([self._adb_path, "shell", "pm list packages"], - stdout=subprocess.PIPE, stderr=subprocess.PIPE) - names = [] - for line in p.stdout.readlines(): - line = re.sub("(^package:)|\s", "", line) - if self._INTENT_PREFIX in line: - names.append(line.replace(self._INTENT_PREFIX, "")) - return names - - -class XulrunnerAppProfile(mozrunner.Profile): - preferences = {} - names = [] - -class XulrunnerAppRunner(mozrunner.Runner): - """ - Runner for any XULRunner app. Can use a Firefox binary in XULRunner - mode to execute the app, or can use XULRunner itself. Expects the - app's application.ini to be passed in as one of the items in - 'cmdargs' in the constructor. - - This class relies a lot on the particulars of mozrunner.Runner's - implementation, and does some unfortunate acrobatics to get around - some of the class' limitations/assumptions. - """ - - profile_class = XulrunnerAppProfile - - # This is a default, and will be overridden in the instance if - # Firefox is used in XULRunner mode. - names = ['xulrunner'] - - # Default location of XULRunner on OS X. - __DARWIN_PATH = "/Library/Frameworks/XUL.framework/xulrunner-bin" - __LINUX_PATH = "/usr/bin/xulrunner" - - # What our application.ini's path looks like if it's part of - # an "installed" XULRunner app on OS X. - __DARWIN_APP_INI_SUFFIX = '.app/Contents/Resources/application.ini' - - def __init__(self, binary=None, **kwargs): - if sys.platform == 'darwin' and binary and binary.endswith('.app'): - # Assume it's a Firefox app dir. - binary = os.path.join(binary, 'Contents/MacOS/firefox-bin') - - self.__app_ini = None - self.__real_binary = binary - - mozrunner.Runner.__init__(self, **kwargs) - - # See if we're using a genuine xulrunner-bin from the XULRunner SDK, - # or if we're being asked to use Firefox in XULRunner mode. - self.__is_xulrunner_sdk = 'xulrunner' in self.binary - - if sys.platform == 'linux2' and not self.env.get('LD_LIBRARY_PATH'): - self.env['LD_LIBRARY_PATH'] = os.path.dirname(self.binary) - - newargs = [] - for item in self.cmdargs: - if 'application.ini' in item: - self.__app_ini = item - else: - newargs.append(item) - self.cmdargs = newargs - - if not self.__app_ini: - raise ValueError('application.ini not found in cmdargs') - if not os.path.exists(self.__app_ini): - raise ValueError("file does not exist: '%s'" % self.__app_ini) - - if (sys.platform == 'darwin' and - self.binary == self.__DARWIN_PATH and - self.__app_ini.endswith(self.__DARWIN_APP_INI_SUFFIX)): - # If the application.ini is in an app bundle, then - # it could be inside an "installed" XULRunner app. - # If this is the case, use the app's actual - # binary instead of the XUL framework's, so we get - # a proper app icon, etc. - new_binary = '/'.join(self.__app_ini.split('/')[:-2] + - ['MacOS', 'xulrunner']) - if os.path.exists(new_binary): - self.binary = new_binary - - @property - def command(self): - """Returns the command list to run.""" - - if self.__is_xulrunner_sdk: - return [self.binary, self.__app_ini, '-profile', - self.profile.profile] - else: - return [self.binary, '-app', self.__app_ini, '-profile', - self.profile.profile] - - def __find_xulrunner_binary(self): - if sys.platform == 'darwin': - if os.path.exists(self.__DARWIN_PATH): - return self.__DARWIN_PATH - if sys.platform == 'linux2': - if os.path.exists(self.__LINUX_PATH): - return self.__LINUX_PATH - return None - - def find_binary(self): - # This gets called by the superclass constructor. It will - # always get called, even if a binary was passed into the - # constructor, because we want to have full control over - # what the exact setting of self.binary is. - - if not self.__real_binary: - self.__real_binary = self.__find_xulrunner_binary() - if not self.__real_binary: - dummy_profile = {} - runner = mozrunner.FirefoxRunner(profile=dummy_profile) - self.__real_binary = runner.find_binary() - self.names = runner.names - return self.__real_binary - -def set_overloaded_modules(env_root, app_type, addon_id, preferences, overloads): - # win32 file scheme needs 3 slashes - desktop_file_scheme = "file://" - if not env_root.startswith("/"): - desktop_file_scheme = desktop_file_scheme + "/" - - pref_prefix = "extensions.modules." + addon_id + ".path" - - # Set preferences that will map require prefix to a given path - for name, path in overloads.items(): - if len(name) == 0: - prefName = pref_prefix - else: - prefName = pref_prefix + "." + name - if app_type == "fennec-on-device": - # For testing on device, we have to copy overloaded files from fs - # to the device and use device path instead of local fs path. - # Actual copy of files if done after the call to Profile constructor - preferences[prefName] = "file://" + \ - FENNEC_REMOTE_PATH + "/overloads/" + name - else: - preferences[prefName] = desktop_file_scheme + \ - path.replace("\\", "/") + "/" - -def run_app(harness_root_dir, manifest_rdf, harness_options, - app_type, binary=None, profiledir=None, verbose=False, - parseable=False, enforce_timeouts=False, - logfile=None, addons=None, args=None, extra_environment={}, - norun=None, noquit=None, - used_files=None, enable_mobile=False, - mobile_app_name=None, - env_root=None, - is_running_tests=False, - overload_modules=False, - bundle_sdk=True, - pkgdir="", - enable_e10s=False, - no_connections=False): - if binary: - binary = os.path.expanduser(binary) - - if addons is None: - addons = [] - else: - addons = list(addons) - - cmdargs = [] - preferences = dict(DEFAULT_COMMON_PREFS) - - if is_running_tests: - preferences.update(DEFAULT_TEST_PREFS) - - if no_connections: - preferences.update(DEFAULT_NO_CONNECTIONS_PREFS) - - if enable_e10s: - preferences['browser.tabs.remote.autostart'] = True - else: - preferences['browser.tabs.remote.autostart'] = False - preferences['browser.tabs.remote.autostart.1'] = False - preferences['browser.tabs.remote.autostart.2'] = False - - # For now, only allow running on Mobile with --force-mobile argument - if app_type in ["fennec-on-device"] and not enable_mobile: - print """ - WARNING: Firefox Mobile support is still experimental. - If you would like to run an addon on this platform, use --force-mobile flag: - - cfx --force-mobile""" - return 0 - - if app_type == "fennec-on-device": - profile_class = FennecProfile - preferences.update(DEFAULT_FENNEC_PREFS) - runner_class = RemoteFennecRunner - # We pass the intent name through command arguments - cmdargs.append(mobile_app_name) - elif app_type == "xulrunner": - profile_class = XulrunnerAppProfile - runner_class = XulrunnerAppRunner - cmdargs.append(os.path.join(harness_root_dir, 'application.ini')) - elif app_type == "firefox": - profile_class = mozrunner.FirefoxProfile - preferences.update(DEFAULT_FIREFOX_PREFS) - runner_class = mozrunner.FirefoxRunner - elif app_type == "thunderbird": - profile_class = mozrunner.ThunderbirdProfile - preferences.update(DEFAULT_THUNDERBIRD_PREFS) - runner_class = mozrunner.ThunderbirdRunner - else: - raise ValueError("Unknown app: %s" % app_type) - if sys.platform == 'darwin' and app_type != 'xulrunner': - cmdargs.append('-foreground') - - if args: - cmdargs.extend(shlex.split(args)) - - # TODO: handle logs on remote device - if app_type != "fennec-on-device": - # tempfile.gettempdir() was constant, preventing two simultaneous "cfx - # run"/"cfx test" on the same host. On unix it points at /tmp (which is - # world-writeable), enabling a symlink attack (e.g. imagine some bad guy - # does 'ln -s ~/.ssh/id_rsa /tmp/harness_result'). NamedTemporaryFile - # gives us a unique filename that fixes both problems. We leave the - # (0-byte) file in place until the browser-side code starts writing to - # it, otherwise the symlink attack becomes possible again. - fileno,resultfile = tempfile.mkstemp(prefix="harness-result-") - os.close(fileno) - harness_options['resultFile'] = resultfile - - def maybe_remove_logfile(): - if os.path.exists(logfile): - os.remove(logfile) - - logfile_tail = None - - # We always buffer output through a logfile for two reasons: - # 1. On Windows, it's the only way to print console output to stdout/err. - # 2. It enables us to keep track of the last time output was emitted, - # so we can raise an exception if the test runner hangs. - if not logfile: - fileno,logfile = tempfile.mkstemp(prefix="harness-log-") - os.close(fileno) - logfile_tail = follow_file(logfile) - atexit.register(maybe_remove_logfile) - - logfile = os.path.abspath(os.path.expanduser(logfile)) - maybe_remove_logfile() - - env = {} - env.update(os.environ) - if no_connections: - env['MOZ_DISABLE_NONLOCAL_CONNECTIONS'] = '1' - env['MOZ_NO_REMOTE'] = '1' - env['XPCOM_DEBUG_BREAK'] = 'stack' - env.update(extra_environment) - if norun: - cmdargs.append("-no-remote") - - # Create the addon XPI so mozrunner will copy it to the profile it creates. - # We delete it below after getting mozrunner to create the profile. - from cuddlefish.xpi import build_xpi - xpi_path = tempfile.mktemp(suffix='cfx-tmp.xpi') - build_xpi(template_root_dir=harness_root_dir, - manifest=manifest_rdf, - xpi_path=xpi_path, - harness_options=harness_options, - limit_to=used_files, - bundle_sdk=bundle_sdk, - pkgdir=pkgdir) - addons.append(xpi_path) - - starttime = last_output_time = time.time() - - # Redirect runner output to a file so we can catch output not generated - # by us. - # In theory, we could do this using simple redirection on all platforms - # other than Windows, but this way we only have a single codepath to - # maintain. - fileno,outfile = tempfile.mkstemp(prefix="harness-stdout-") - os.close(fileno) - outfile_tail = follow_file(outfile) - def maybe_remove_outfile(): - if os.path.exists(outfile): - try: - os.remove(outfile) - except Exception, e: - print "Error Cleaning up: " + str(e) - atexit.register(maybe_remove_outfile) - outf = open(outfile, "w") - popen_kwargs = { 'stdout': outf, 'stderr': outf} - - profile = None - - if app_type == "fennec-on-device": - # Install a special addon when we run firefox on mobile device - # in order to be able to kill it - mydir = os.path.dirname(os.path.abspath(__file__)) - addon_dir = os.path.join(mydir, "mobile-utils") - addons.append(addon_dir) - - # Overload addon-specific commonjs modules path with lib/ folder - overloads = dict() - if overload_modules: - overloads[""] = os.path.join(env_root, "lib") - - # Overload tests/ mapping with test/ folder, only when running test - if is_running_tests: - overloads["tests"] = os.path.join(env_root, "test") - - set_overloaded_modules(env_root, app_type, harness_options["jetpackID"], \ - preferences, overloads) - - # the XPI file is copied into the profile here - profile = profile_class(addons=addons, - profile=profiledir, - preferences=preferences) - - # Delete the temporary xpi file - os.remove(xpi_path) - - # Copy overloaded files registered in set_overloaded_modules - # For testing on device, we have to copy overloaded files from fs - # to the device and use device path instead of local fs path. - # (has to be done after the call to profile_class() which eventualy creates - # profile folder) - if app_type == "fennec-on-device": - profile_path = profile.profile - for name, path in overloads.items(): - shutil.copytree(path, \ - os.path.join(profile_path, "overloads", name)) - - runner = runner_class(profile=profile, - binary=binary, - env=env, - cmdargs=cmdargs, - kp_kwargs=popen_kwargs) - - sys.stdout.flush(); sys.stderr.flush() - - if app_type == "fennec-on-device": - if not enable_mobile: - print >>sys.stderr, """ - WARNING: Firefox Mobile support is still experimental. - If you would like to run an addon on this platform, use --force-mobile flag: - - cfx --force-mobile""" - return 0 - - # In case of mobile device, we need to get stdio from `adb logcat` cmd: - - # First flush logs in order to avoid catching previous ones - subprocess.call([binary, "logcat", "-c"]) - - # Launch adb command - runner.start() - - # We can immediatly remove temporary profile folder - # as it has been uploaded to the device - profile.cleanup() - # We are not going to use the output log file - outf.close() - - # Then we simply display stdout of `adb logcat` - p = subprocess.Popen([binary, "logcat", "stderr:V stdout:V GeckoConsole:V *:S"], stdout=subprocess.PIPE) - while True: - line = p.stdout.readline() - if line == '': - break - # mobile-utils addon contains an application quit event observer - # that will print this string: - if "APPLICATION-QUIT" in line: - break - - if verbose: - # if --verbose is given, we display everything: - # All JS Console messages, stdout and stderr. - m = CLEANUP_ADB.match(line) - if not m: - print line.rstrip() - continue - print m.group(3) - else: - # Otherwise, display addons messages dispatched through - # console.[info, log, debug, warning, error](msg) - m = FILTER_ONLY_CONSOLE_FROM_ADB.match(line) - if m: - print m.group(2) - - print >>sys.stderr, "Program terminated successfully." - return 0 - - - print >>sys.stderr, "Using binary at '%s'." % runner.binary - - # Ensure cfx is being used with Firefox 4.0+. - # TODO: instead of dying when Firefox is < 4, warn when Firefox is outside - # the minVersion/maxVersion boundaries. - version_output = check_output(runner.command + ["-v"]) - # Note: this regex doesn't handle all valid versions in the Toolkit Version - # Format , just the - # common subset that we expect Mozilla apps to use. - mo = re.search(r"Mozilla (Firefox|Iceweasel|Fennec)\b[^ ]* ((\d+)\.\S*)", - version_output) - if not mo: - # cfx may be used with Thunderbird, SeaMonkey or an exotic Firefox - # version. - print """ - WARNING: cannot determine Firefox version; please ensure you are running - a Mozilla application equivalent to Firefox 4.0 or greater. - """ - elif mo.group(1) == "Fennec": - # For now, only allow running on Mobile with --force-mobile argument - if not enable_mobile: - print """ - WARNING: Firefox Mobile support is still experimental. - If you would like to run an addon on this platform, use --force-mobile flag: - - cfx --force-mobile""" - return - else: - version = mo.group(3) - if int(version) < 4: - print """ - cfx requires Firefox 4 or greater and is unable to find a compatible - binary. Please install a newer version of Firefox or provide the path to - your existing compatible version with the --binary flag: - - cfx --binary=PATH_TO_FIREFOX_BINARY""" - return - - # Set the appropriate extensions.checkCompatibility preference to false, - # so the tests run even if the SDK is not marked as compatible with the - # version of Firefox on which they are running, and we don't have to - # ensure we update the maxVersion before the version of Firefox changes - # every six weeks. - # - # The regex we use here is effectively the same as BRANCH_REGEX from - # /toolkit/mozapps/extensions/content/extensions.js, which toolkit apps - # use to determine whether or not to load an incompatible addon. - # - br = re.search(r"^([^\.]+\.[0-9]+[a-z]*).*", mo.group(2), re.I) - if br: - prefname = 'extensions.checkCompatibility.' + br.group(1) - profile.preferences[prefname] = False - # Calling profile.set_preferences here duplicates the list of prefs - # in prefs.js, since the profile calls self.set_preferences in its - # constructor, but that is ok, because it doesn't change the set of - # preferences that are ultimately registered in Firefox. - profile.set_preferences(profile.preferences) - - print >>sys.stderr, "Using profile at '%s'." % profile.profile - sys.stderr.flush() - - if norun: - print "To launch the application, enter the following command:" - print " ".join(runner.command) + " " + (" ".join(runner.cmdargs)) - return 0 - - runner.start() - - done = False - result = None - test_name = "Jetpack startup" - - def Timeout(message, test_name, parseable): - if parseable: - sys.stderr.write("TEST-UNEXPECTED-FAIL | %s | %s\n" % (test_name, message)) - sys.stderr.flush() - return Exception(message) - - try: - while not done: - time.sleep(0.05) - for tail in (logfile_tail, outfile_tail): - if tail: - new_chars = tail.next() - if new_chars: - last_output_time = time.time() - sys.stderr.write(new_chars) - sys.stderr.flush() - if is_running_tests and parseable: - match = PARSEABLE_TEST_NAME.search(new_chars) - if match: - test_name = match.group(1) - if os.path.exists(resultfile): - result = open(resultfile).read() - if result: - if result in ['OK', 'FAIL']: - done = True - else: - sys.stderr.write("Hrm, resultfile (%s) contained something weird (%d bytes)\n" % (resultfile, len(result))) - sys.stderr.write("'"+result+"'\n") - if enforce_timeouts: - if time.time() - last_output_time > OUTPUT_TIMEOUT: - raise Timeout("Test output exceeded timeout (%ds)." % - OUTPUT_TIMEOUT, test_name, parseable) - if time.time() - starttime > RUN_TIMEOUT: - raise Timeout("Test run exceeded timeout (%ds)." % - RUN_TIMEOUT, test_name, parseable) - except: - if not noquit: - runner.stop() - raise - else: - runner.wait(10) - # double kill - hack for bugs 942111, 1006043.. - try: - runner.stop() - except: - pass - finally: - outf.close() - if profile: - profile.cleanup() - - print >>sys.stderr, "Total time: %f seconds" % (time.time() - starttime) - - if result == 'OK': - print >>sys.stderr, "Program terminated successfully." - return 0 - else: - print >>sys.stderr, "Program terminated unsuccessfully." - return -1 diff --git a/addon-sdk/source/python-lib/cuddlefish/templates.py b/addon-sdk/source/python-lib/cuddlefish/templates.py deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/templates.py +++ /dev/null @@ -1,32 +0,0 @@ -# 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/. - -#Template used by test-main.js -TEST_MAIN_JS = '''\ -var main = require("./main"); - -exports["test main"] = function(assert) { - assert.pass("Unit test running!"); -}; - -exports["test main async"] = function(assert, done) { - assert.pass("async Unit test running!"); - done(); -}; - -require("sdk/test").run(exports); -''' - -#Template used by package.json -PACKAGE_JSON = '''\ -{ - "name": "%(name)s", - "title": "%(title)s", - "id": "%(id)s", - "description": "a basic add-on", - "author": "", - "license": "MPL-2.0", - "version": "0.1" -} -''' diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/__init__.py b/addon-sdk/source/python-lib/cuddlefish/tests/__init__.py deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/__init__.py +++ /dev/null @@ -1,52 +0,0 @@ -# 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/. - -import os -import unittest -import doctest -import glob - -env_root = os.environ['CUDDLEFISH_ROOT'] - -def get_tests(): - import cuddlefish - import cuddlefish.tests - - tests = [] - packages = [cuddlefish, cuddlefish.tests] - for package in packages: - path = os.path.abspath(package.__path__[0]) - pynames = glob.glob(os.path.join(path, '*.py')) - for filename in pynames: - basename = os.path.basename(filename) - module_name = os.path.splitext(basename)[0] - full_name = "%s.%s" % (package.__name__, module_name) - module = __import__(full_name, fromlist=[package.__name__]) - - loader = unittest.TestLoader() - suite = loader.loadTestsFromModule(module) - for test in suite: - tests.append(test) - - finder = doctest.DocTestFinder() - doctests = finder.find(module) - for test in doctests: - if len(test.examples) > 0: - tests.append(doctest.DocTestCase(test)) - - return tests - -def run(verbose=False): - if verbose: - verbosity = 2 - else: - verbosity = 1 - - tests = get_tests() - suite = unittest.TestSuite(tests) - runner = unittest.TextTestRunner(verbosity=verbosity) - return runner.run(suite) - -if __name__ == '__main__': - run() diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/bug-588119-files/packages/explicit-icon/explicit-icon.png b/addon-sdk/source/python-lib/cuddlefish/tests/bug-588119-files/packages/explicit-icon/explicit-icon.png deleted file mode 100644 diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/bug-588119-files/packages/explicit-icon/explicit-icon64.png b/addon-sdk/source/python-lib/cuddlefish/tests/bug-588119-files/packages/explicit-icon/explicit-icon64.png deleted file mode 100644 diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/bug-588119-files/packages/explicit-icon/lib/main.js b/addon-sdk/source/python-lib/cuddlefish/tests/bug-588119-files/packages/explicit-icon/lib/main.js deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-588119-files/packages/explicit-icon/lib/main.js +++ /dev/null @@ -1,4 +0,0 @@ -/* 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/. */ - diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/bug-588119-files/packages/explicit-icon/package.json b/addon-sdk/source/python-lib/cuddlefish/tests/bug-588119-files/packages/explicit-icon/package.json deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-588119-files/packages/explicit-icon/package.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "loader": "lib/main.js", - "icon": "explicit-icon.png", - "icon64": "explicit-icon64.png" -} diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/bug-588119-files/packages/implicit-icon/icon.png b/addon-sdk/source/python-lib/cuddlefish/tests/bug-588119-files/packages/implicit-icon/icon.png deleted file mode 100644 diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/bug-588119-files/packages/implicit-icon/icon64.png b/addon-sdk/source/python-lib/cuddlefish/tests/bug-588119-files/packages/implicit-icon/icon64.png deleted file mode 100644 diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/bug-588119-files/packages/implicit-icon/lib/main.js b/addon-sdk/source/python-lib/cuddlefish/tests/bug-588119-files/packages/implicit-icon/lib/main.js deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-588119-files/packages/implicit-icon/lib/main.js +++ /dev/null @@ -1,4 +0,0 @@ -/* 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/. */ - diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/bug-588119-files/packages/implicit-icon/package.json b/addon-sdk/source/python-lib/cuddlefish/tests/bug-588119-files/packages/implicit-icon/package.json deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-588119-files/packages/implicit-icon/package.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "loader": "lib/main.js" -} diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/bug-588119-files/packages/no-icon/lib/main.js b/addon-sdk/source/python-lib/cuddlefish/tests/bug-588119-files/packages/no-icon/lib/main.js deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-588119-files/packages/no-icon/lib/main.js +++ /dev/null @@ -1,4 +0,0 @@ -/* 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/. */ - diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/bug-588119-files/packages/no-icon/package.json b/addon-sdk/source/python-lib/cuddlefish/tests/bug-588119-files/packages/no-icon/package.json deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-588119-files/packages/no-icon/package.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "loader": "lib/main.js" -} diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/bug-588661-files/packages/bar/lib/bar-loader.js b/addon-sdk/source/python-lib/cuddlefish/tests/bug-588661-files/packages/bar/lib/bar-loader.js deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-588661-files/packages/bar/lib/bar-loader.js +++ /dev/null @@ -1,4 +0,0 @@ -/* 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/. */ - diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/bug-588661-files/packages/bar/package.json b/addon-sdk/source/python-lib/cuddlefish/tests/bug-588661-files/packages/bar/package.json deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-588661-files/packages/bar/package.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "loader": "lib/bar-loader.js" -} diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/bug-588661-files/packages/foo/lib/foo-loader.js b/addon-sdk/source/python-lib/cuddlefish/tests/bug-588661-files/packages/foo/lib/foo-loader.js deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-588661-files/packages/foo/lib/foo-loader.js +++ /dev/null @@ -1,4 +0,0 @@ -/* 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/. */ - diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/bug-588661-files/packages/foo/package.json b/addon-sdk/source/python-lib/cuddlefish/tests/bug-588661-files/packages/foo/package.json deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-588661-files/packages/foo/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "loader": "lib/foo-loader.js", - "dependencies": ["bar"] -} diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/bug-611495-files/jspath-one/docs/main.md b/addon-sdk/source/python-lib/cuddlefish/tests/bug-611495-files/jspath-one/docs/main.md deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-611495-files/jspath-one/docs/main.md +++ /dev/null @@ -1,5 +0,0 @@ - - -minimal docs diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/bug-611495-files/jspath-one/lib/main.js b/addon-sdk/source/python-lib/cuddlefish/tests/bug-611495-files/jspath-one/lib/main.js deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-611495-files/jspath-one/lib/main.js +++ /dev/null @@ -1,8 +0,0 @@ -/* 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/. */ - -exports.main = function(options, callbacks) { - console.log("minimal"); - callbacks.quit(); -}; diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/bug-611495-files/jspath-one/package.json b/addon-sdk/source/python-lib/cuddlefish/tests/bug-611495-files/jspath-one/package.json deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-611495-files/jspath-one/package.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "jspath-one", - "author": "Jon Smith", - "description": "A package w/ a main module; can be built into an extension." -} diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/bug-614712-files/packages/commonjs-naming/doc/foo.md b/addon-sdk/source/python-lib/cuddlefish/tests/bug-614712-files/packages/commonjs-naming/doc/foo.md deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-614712-files/packages/commonjs-naming/doc/foo.md +++ /dev/null @@ -1,5 +0,0 @@ - - -I am documentation for foo. diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/bug-614712-files/packages/commonjs-naming/lib/foo-loader.js b/addon-sdk/source/python-lib/cuddlefish/tests/bug-614712-files/packages/commonjs-naming/lib/foo-loader.js deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-614712-files/packages/commonjs-naming/lib/foo-loader.js +++ /dev/null @@ -1,5 +0,0 @@ -/* 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/. */ - - diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/bug-614712-files/packages/commonjs-naming/package.json b/addon-sdk/source/python-lib/cuddlefish/tests/bug-614712-files/packages/commonjs-naming/package.json deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-614712-files/packages/commonjs-naming/package.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "loader": "lib/foo-loader.js" -} diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/bug-614712-files/packages/commonjs-naming/test/test-foo.js b/addon-sdk/source/python-lib/cuddlefish/tests/bug-614712-files/packages/commonjs-naming/test/test-foo.js deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-614712-files/packages/commonjs-naming/test/test-foo.js +++ /dev/null @@ -1,7 +0,0 @@ -/* 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/. */ - -exports.testThing = function(test) { - test.assertEqual(2, 1 + 1); -}; diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/bug-614712-files/packages/original-naming/docs/foo.md b/addon-sdk/source/python-lib/cuddlefish/tests/bug-614712-files/packages/original-naming/docs/foo.md deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-614712-files/packages/original-naming/docs/foo.md +++ /dev/null @@ -1,5 +0,0 @@ - - -I am documentation for foo. diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/bug-614712-files/packages/original-naming/lib/foo-loader.js b/addon-sdk/source/python-lib/cuddlefish/tests/bug-614712-files/packages/original-naming/lib/foo-loader.js deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-614712-files/packages/original-naming/lib/foo-loader.js +++ /dev/null @@ -1,5 +0,0 @@ -/* 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/. */ - - diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/bug-614712-files/packages/original-naming/package.json b/addon-sdk/source/python-lib/cuddlefish/tests/bug-614712-files/packages/original-naming/package.json deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-614712-files/packages/original-naming/package.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "loader": "lib/foo-loader.js" -} diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/bug-614712-files/packages/original-naming/tests/test-foo.js b/addon-sdk/source/python-lib/cuddlefish/tests/bug-614712-files/packages/original-naming/tests/test-foo.js deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-614712-files/packages/original-naming/tests/test-foo.js +++ /dev/null @@ -1,7 +0,0 @@ -/* 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/. */ - -exports.testThing = function(test) { - test.assertEqual(2, 1 + 1); -}; diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/default-lib/doc/foo.md b/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/default-lib/doc/foo.md deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/default-lib/doc/foo.md +++ /dev/null @@ -1,5 +0,0 @@ - - -I am documentation for foo. diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/default-lib/lib/foo.js b/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/default-lib/lib/foo.js deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/default-lib/lib/foo.js +++ /dev/null @@ -1,5 +0,0 @@ -/* 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/. */ - - diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/default-lib/lib/loader.js b/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/default-lib/lib/loader.js deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/default-lib/lib/loader.js +++ /dev/null @@ -1,5 +0,0 @@ -/* 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/. */ - - diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/default-lib/package.json b/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/default-lib/package.json deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/default-lib/package.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "loader": "lib/loader.js" -} diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/default-lib/test/test-foo.js b/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/default-lib/test/test-foo.js deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/default-lib/test/test-foo.js +++ /dev/null @@ -1,7 +0,0 @@ -/* 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/. */ - -exports.testThing = function(test) { - test.assertEqual(2, 1 + 1); -}; diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/default-locale/locale/emptyFolder b/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/default-locale/locale/emptyFolder deleted file mode 100644 diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/default-locale/package.json b/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/default-locale/package.json deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/default-locale/package.json +++ /dev/null @@ -1,1 +0,0 @@ -{} diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/default-root/doc/foo.md b/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/default-root/doc/foo.md deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/default-root/doc/foo.md +++ /dev/null @@ -1,5 +0,0 @@ - - -I am documentation for foo. diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/default-root/foo.js b/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/default-root/foo.js deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/default-root/foo.js +++ /dev/null @@ -1,5 +0,0 @@ -/* 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/. */ - - diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/default-root/loader.js b/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/default-root/loader.js deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/default-root/loader.js +++ /dev/null @@ -1,5 +0,0 @@ -/* 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/. */ - - diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/default-root/package.json b/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/default-root/package.json deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/default-root/package.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "loader": "loader.js" -} diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/default-root/test/test-foo.js b/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/default-root/test/test-foo.js deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/default-root/test/test-foo.js +++ /dev/null @@ -1,7 +0,0 @@ -/* 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/. */ - -exports.testThing = function(test) { - test.assertEqual(2, 1 + 1); -}; diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/explicit-dir-lib/alt-lib/foo.js b/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/explicit-dir-lib/alt-lib/foo.js deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/explicit-dir-lib/alt-lib/foo.js +++ /dev/null @@ -1,5 +0,0 @@ -/* 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/. */ - - diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/explicit-dir-lib/alt-lib/loader.js b/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/explicit-dir-lib/alt-lib/loader.js deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/explicit-dir-lib/alt-lib/loader.js +++ /dev/null @@ -1,5 +0,0 @@ -/* 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/. */ - - diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/explicit-dir-lib/doc/foo.md b/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/explicit-dir-lib/doc/foo.md deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/explicit-dir-lib/doc/foo.md +++ /dev/null @@ -1,5 +0,0 @@ - - -I am documentation for foo. diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/explicit-dir-lib/package.json b/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/explicit-dir-lib/package.json deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/explicit-dir-lib/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "directories": { "lib": "./alt-lib" }, - "loader": "alt-lib/loader.js" -} diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/explicit-dir-lib/test/test-foo.js b/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/explicit-dir-lib/test/test-foo.js deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/explicit-dir-lib/test/test-foo.js +++ /dev/null @@ -1,7 +0,0 @@ -/* 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/. */ - -exports.testThing = function(test) { - test.assertEqual(2, 1 + 1); -}; diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/explicit-lib/alt2-lib/foo.js b/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/explicit-lib/alt2-lib/foo.js deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/explicit-lib/alt2-lib/foo.js +++ /dev/null @@ -1,5 +0,0 @@ -/* 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/. */ - - diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/explicit-lib/alt2-lib/loader.js b/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/explicit-lib/alt2-lib/loader.js deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/explicit-lib/alt2-lib/loader.js +++ /dev/null @@ -1,5 +0,0 @@ -/* 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/. */ - - diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/explicit-lib/doc/foo.md b/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/explicit-lib/doc/foo.md deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/explicit-lib/doc/foo.md +++ /dev/null @@ -1,5 +0,0 @@ - - -I am documentation for foo. diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/explicit-lib/package.json b/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/explicit-lib/package.json deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/explicit-lib/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "lib": "./alt2-lib", - "loader": "alt2-lib/loader.js" -} diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/explicit-lib/test/test-foo.js b/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/explicit-lib/test/test-foo.js deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-652227-files/packages/explicit-lib/test/test-foo.js +++ /dev/null @@ -1,7 +0,0 @@ -/* 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/. */ - -exports.testThing = function(test) { - test.assertEqual(2, 1 + 1); -}; diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/bug-669274-files/packages/extra-options/docs/main.md b/addon-sdk/source/python-lib/cuddlefish/tests/bug-669274-files/packages/extra-options/docs/main.md deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-669274-files/packages/extra-options/docs/main.md +++ /dev/null @@ -1,5 +0,0 @@ - - -minimal docs diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/bug-669274-files/packages/extra-options/lib/main.js b/addon-sdk/source/python-lib/cuddlefish/tests/bug-669274-files/packages/extra-options/lib/main.js deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-669274-files/packages/extra-options/lib/main.js +++ /dev/null @@ -1,8 +0,0 @@ -/* 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/. */ - -exports.main = function(options, callbacks) { - console.log("minimal"); - callbacks.quit(); -}; diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/bug-669274-files/packages/extra-options/package.json b/addon-sdk/source/python-lib/cuddlefish/tests/bug-669274-files/packages/extra-options/package.json deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-669274-files/packages/extra-options/package.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "extra-options", - "author": "Jon Smith", - "description": "A package w/ a main module; can be built into an extension.", - "loader": "lib/main.js" -} diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/bug-715340-files/pkg-1-pack/package.json b/addon-sdk/source/python-lib/cuddlefish/tests/bug-715340-files/pkg-1-pack/package.json deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-715340-files/pkg-1-pack/package.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "name": "empty", - "license": "MPL-2.0", - "author": "", - "version": "0.1", - "title": "empty", - "id": "jid1-80fr8b6qeRlQSQ", - "unpack": false, - "description": "test unpack= support" -} diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/bug-715340-files/pkg-2-unpack/package.json b/addon-sdk/source/python-lib/cuddlefish/tests/bug-715340-files/pkg-2-unpack/package.json deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-715340-files/pkg-2-unpack/package.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "name": "empty", - "license": "MPL-2.0", - "author": "", - "version": "0.1", - "title": "empty", - "id": "jid1-80fr8b6qeRlQSQ", - "unpack": true, - "description": "test unpack= support" -} diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/bug-715340-files/pkg-3-pack/package.json b/addon-sdk/source/python-lib/cuddlefish/tests/bug-715340-files/pkg-3-pack/package.json deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-715340-files/pkg-3-pack/package.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "empty", - "license": "MPL-2.0", - "author": "", - "version": "0.1", - "title": "empty", - "id": "jid1-80fr8b6qeRlQSQ", - "description": "test unpack= support" -} diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/bug-906359-files/fullName/package.json b/addon-sdk/source/python-lib/cuddlefish/tests/bug-906359-files/fullName/package.json deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-906359-files/fullName/package.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "empty", - "license": "MPL-2.0", - "author": "", - "version": "0.1", - "fullName": "a long fullName", - "id": "jid1-80123", - "description": "test addon name fallback to 'fullName' key" -} diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/bug-906359-files/none/package.json b/addon-sdk/source/python-lib/cuddlefish/tests/bug-906359-files/none/package.json deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-906359-files/none/package.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "a long none", - "license": "MPL-2.0", - "author": "", - "version": "0.1", - - "id": "jid1-80123", - "description": "test addon name falls back all the way to the 'name' key" -} diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/bug-906359-files/title/package.json b/addon-sdk/source/python-lib/cuddlefish/tests/bug-906359-files/title/package.json deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-906359-files/title/package.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "empty", - "license": "MPL-2.0", - "author": "", - "version": "0.1", - "title": "a long title", - "id": "jid1-80123", - "description": "test addon name comes from the 'title' key" -} diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/e10s-adapter-files/packages/foo/lib/bar-e10s-adapter.js b/addon-sdk/source/python-lib/cuddlefish/tests/e10s-adapter-files/packages/foo/lib/bar-e10s-adapter.js deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/e10s-adapter-files/packages/foo/lib/bar-e10s-adapter.js +++ /dev/null @@ -1,11 +0,0 @@ -/* 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/. */ - -if (this.sendMessage) { -} else { - require('bar'); - - exports.register = function(process) { - }; -} diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/e10s-adapter-files/packages/foo/lib/bar.js b/addon-sdk/source/python-lib/cuddlefish/tests/e10s-adapter-files/packages/foo/lib/bar.js deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/e10s-adapter-files/packages/foo/lib/bar.js +++ /dev/null @@ -1,5 +0,0 @@ -/* 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/. */ - -require('chrome'); diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/e10s-adapter-files/packages/foo/lib/foo.js b/addon-sdk/source/python-lib/cuddlefish/tests/e10s-adapter-files/packages/foo/lib/foo.js deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/e10s-adapter-files/packages/foo/lib/foo.js +++ /dev/null @@ -1,5 +0,0 @@ -/* 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/. */ - -require('bar'); diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/e10s-adapter-files/packages/foo/package.json b/addon-sdk/source/python-lib/cuddlefish/tests/e10s-adapter-files/packages/foo/package.json deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/e10s-adapter-files/packages/foo/package.json +++ /dev/null @@ -1,1 +0,0 @@ -{} diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/five/lib/main.js b/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/five/lib/main.js deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/five/lib/main.js +++ /dev/null @@ -1,5 +0,0 @@ -/* 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/. */ - -exports.main = "'main' mainly reigns in main(.js)"; diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/five/package.json b/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/five/package.json deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/five/package.json +++ /dev/null @@ -1,3 +0,0 @@ -{ "name": "five", - "main": "./lib/main" -} diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/four-deps/four-a/lib/misc.js b/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/four-deps/four-a/lib/misc.js deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/four-deps/four-a/lib/misc.js +++ /dev/null @@ -1,5 +0,0 @@ -/* 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/. */ - -exports.main = 42; diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/four-deps/four-a/package.json b/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/four-deps/four-a/package.json deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/four-deps/four-a/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ "name": "four-a", - "directories": {"lib": "lib"}, - "main": "./topfiles/main.js" -} diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/four-deps/four-a/topfiles/main.js b/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/four-deps/four-a/topfiles/main.js deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/four-deps/four-a/topfiles/main.js +++ /dev/null @@ -1,5 +0,0 @@ -/* 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/. */ - -exports.main = 42; diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/four/lib/main.js b/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/four/lib/main.js deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/four/lib/main.js +++ /dev/null @@ -1,5 +0,0 @@ -/* 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/. */ - -var a = require("four-a"); diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/four/package.json b/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/four/package.json deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/four/package.json +++ /dev/null @@ -1,3 +0,0 @@ -{ "name": "four", - "main": "main" -} diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/one/lib/main.js b/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/one/lib/main.js deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/one/lib/main.js +++ /dev/null @@ -1,9 +0,0 @@ -/* 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/. */ - -var panel = require("sdk/panel"); -var two = require("two.js"); -var a = require("./two"); -var b = require("sdk/tabs.js"); -var c = require("./subdir/three"); diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/one/lib/subdir/three.js b/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/one/lib/subdir/three.js deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/one/lib/subdir/three.js +++ /dev/null @@ -1,6 +0,0 @@ -/* 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/. */ - -exports.foo = 1; -var main = require("../main"); diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/one/lib/two.js b/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/one/lib/two.js deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/one/lib/two.js +++ /dev/null @@ -1,8 +0,0 @@ -/* 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/. */ - - -// this ought to find our sibling, not packages/development-mode/lib/main.js -var main = require("main"); -exports.foo = 1; diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/one/package.json b/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/one/package.json deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/one/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ "name": "one", - "id": "jid1@jetpack", - "main": "main" -} diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/seven/data/text.data b/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/seven/data/text.data deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/seven/data/text.data +++ /dev/null @@ -1,1 +0,0 @@ -data diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/seven/lib/main.js b/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/seven/lib/main.js deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/seven/lib/main.js +++ /dev/null @@ -1,6 +0,0 @@ -/* 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/. */ - -var self = require("sdk/self"); // trigger inclusion of data -exports.main = function () { console.log("main"); }; diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/seven/lib/unused.js b/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/seven/lib/unused.js deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/seven/lib/unused.js +++ /dev/null @@ -1,5 +0,0 @@ -/* 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/. */ - -exports.unused = "just pretend I'm not here"; diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/seven/package.json b/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/seven/package.json deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/seven/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "seven", - "id": "jid7" -} diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/six/lib/unused.js b/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/six/lib/unused.js deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/six/lib/unused.js +++ /dev/null @@ -1,5 +0,0 @@ -/* 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/. */ - -exports.unused = "I am."; diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/six/package.json b/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/six/package.json deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/six/package.json +++ /dev/null @@ -1,3 +0,0 @@ -{ "name": "six", - "main": "./unreachable" -} diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/six/unreachable.js b/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/six/unreachable.js deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/six/unreachable.js +++ /dev/null @@ -1,5 +0,0 @@ -/* 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/. */ - -exports.main = "I am outside lib/ and cannot be reached, yet"; diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three-deps/three-a/lib/main.js b/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three-deps/three-a/lib/main.js deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three-deps/three-a/lib/main.js +++ /dev/null @@ -1,8 +0,0 @@ -/* 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/. */ - -exports.main = 42; -require("./subdir/subfile"); -require("sdk/self"); // trigger inclusion of our data/ directory - diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three-deps/three-a/lib/subdir/subfile.js b/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three-deps/three-a/lib/subdir/subfile.js deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three-deps/three-a/lib/subdir/subfile.js +++ /dev/null @@ -1,5 +0,0 @@ -/* 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/. */ - -exports.main = "I should be included in a subdir"; diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three-deps/three-a/lib/unused.js b/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three-deps/three-a/lib/unused.js deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three-deps/three-a/lib/unused.js +++ /dev/null @@ -1,5 +0,0 @@ -/* 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/. */ - -exports.main = "unused, linker should not include me in the XPI"; diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three-deps/three-a/locale/fr-FR.properties b/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three-deps/three-a/locale/fr-FR.properties deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three-deps/three-a/locale/fr-FR.properties +++ /dev/null @@ -1,5 +0,0 @@ -# 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/. - -Yes= Oui diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three-deps/three-a/package.json b/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three-deps/three-a/package.json deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three-deps/three-a/package.json +++ /dev/null @@ -1,3 +0,0 @@ -{ "name": "three-a", - "main": "./lib/main.js" -} diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three-deps/three-b/lib/main.js b/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three-deps/three-b/lib/main.js deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three-deps/three-b/lib/main.js +++ /dev/null @@ -1,5 +0,0 @@ -/* 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/. */ - -exports.main = 42; diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three-deps/three-b/locale/fr-FR.properties b/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three-deps/three-b/locale/fr-FR.properties deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three-deps/three-b/locale/fr-FR.properties +++ /dev/null @@ -1,6 +0,0 @@ -# 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/. - -No= Non -one= un diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three-deps/three-b/package.json b/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three-deps/three-b/package.json deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three-deps/three-b/package.json +++ /dev/null @@ -1,3 +0,0 @@ -{ "name": "three-b", - "main": "./lib/main" -} diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three-deps/three-c/lib/main.js b/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three-deps/three-c/lib/main.js deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three-deps/three-c/lib/main.js +++ /dev/null @@ -1,5 +0,0 @@ -/* 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/. */ - -exports.main = 42; diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three-deps/three-c/lib/sub/foo.js b/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three-deps/three-c/lib/sub/foo.js deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three-deps/three-c/lib/sub/foo.js +++ /dev/null @@ -1,6 +0,0 @@ -/* 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/. */ - -exports.foo = "you found me down here"; - diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three-deps/three-c/locale/fr-FR.properties b/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three-deps/three-c/locale/fr-FR.properties deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three-deps/three-c/locale/fr-FR.properties +++ /dev/null @@ -1,9 +0,0 @@ -# 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/. - -No= Nein -What?= Quoi? -plural=other -plural[one]=one -uft8_value=é diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three-deps/three-c/package.json b/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three-deps/three-c/package.json deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three-deps/three-c/package.json +++ /dev/null @@ -1,3 +0,0 @@ -{ "name": "three-c", - "main": "lib/main" -} diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three/data/msg.txt b/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three/data/msg.txt deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three/data/msg.txt +++ /dev/null @@ -1,1 +0,0 @@ -hello world diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three/data/subdir/submsg.txt b/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three/data/subdir/submsg.txt deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three/data/subdir/submsg.txt +++ /dev/null @@ -1,1 +0,0 @@ -hello subdir diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three/lib/main.js b/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three/lib/main.js deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three/lib/main.js +++ /dev/null @@ -1,8 +0,0 @@ -/* 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/. */ - -var a = require("three-a"); -var b = require("three-b"); -var c = require("three-c"); -var c3 = require("three-c/sub/foo"); diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three/package.json b/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three/package.json deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three/package.json +++ /dev/null @@ -1,3 +0,0 @@ -{ "name": "three", - "main": "main" -} diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three/tests/nontest.js b/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three/tests/nontest.js deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three/tests/nontest.js +++ /dev/null @@ -1,5 +0,0 @@ -/* 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/. */ - -// dummy diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three/tests/test-one.js b/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three/tests/test-one.js deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three/tests/test-one.js +++ /dev/null @@ -1,5 +0,0 @@ -/* 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/. */ - -// dummy diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three/tests/test-two.js b/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three/tests/test-two.js deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/linker-files/three/tests/test-two.js +++ /dev/null @@ -1,5 +0,0 @@ -/* 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/. */ - -// dummy diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/aardvark/doc/main.md b/addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/aardvark/doc/main.md deleted file mode 100644 diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/aardvark/lib/ignore_me b/addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/aardvark/lib/ignore_me deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/aardvark/lib/ignore_me +++ /dev/null @@ -1,3 +0,0 @@ -The docs processor should tolerate (by ignoring) random non-.js files in lib -directories, such as those left around by editors, version-control systems, -or OS metadata like .DS_Store . This file exercises that tolerance. diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/aardvark/lib/main.js b/addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/aardvark/lib/main.js deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/aardvark/lib/main.js +++ /dev/null @@ -1,8 +0,0 @@ -/* 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/. */ - -exports.main = function(options, callbacks) { - console.log("1 + 1 =", require("bar-module").add(1, 1)); - callbacks.quit(); -}; diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/aardvark/lib/surprise.js/ignore_me_too b/addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/aardvark/lib/surprise.js/ignore_me_too deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/aardvark/lib/surprise.js/ignore_me_too +++ /dev/null @@ -1,2 +0,0 @@ -The docs processor should also ignore directories named *.js, and their -contents. diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/aardvark/package.json b/addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/aardvark/package.json deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/aardvark/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "author": "Jon Smith", - "description": "A package w/ a main module; can be built into an extension.", - "keywords": ["potato"], - "version": "1.0", - "dependencies": ["addon-sdk", "barbeque"] -} diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/anteater_files/lib/main.js b/addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/anteater_files/lib/main.js deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/anteater_files/lib/main.js +++ /dev/null @@ -1,8 +0,0 @@ -/* 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/. */ - -exports.main = function(options, callbacks) { - console.log("1 + 1 =", require("bar-module").add(1, 1)); - callbacks.quit(); -}; diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/anteater_files/package.json b/addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/anteater_files/package.json deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/anteater_files/package.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "name": "anteater", - "author": "Jon Smith", - "description": "A package w/ a main module; can be built into an extension.", - "keywords": ["potato"], - "version": "1.0", - "dependencies": ["addon-sdk", "barbeque"] -} diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/api-utils/lib/loader.js b/addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/api-utils/lib/loader.js deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/api-utils/lib/loader.js +++ /dev/null @@ -1,7 +0,0 @@ -/* 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/. */ - -// This module will be imported by the XPCOM harness/boostrapper -// via Components.utils.import() and is responsible for creating a -// CommonJS module loader. diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/api-utils/package.json b/addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/api-utils/package.json deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/api-utils/package.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "description": "A foundational package that provides a CommonJS module loader implementation.", - "keywords": ["potato", "jetpack-low-level"], - "loader": "lib/loader.js" -} diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/barbeque/lib/bar-module.js b/addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/barbeque/lib/bar-module.js deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/barbeque/lib/bar-module.js +++ /dev/null @@ -1,7 +0,0 @@ -/* 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/. */ - -exports.add = function add(a, b) { - return a + b; -}; diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/barbeque/package.json b/addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/barbeque/package.json deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/barbeque/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "keywords": ["potato", "jetpack-low-level"], - "description": "A package used by 'aardvark' as a library." -} diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/minimal/lib/main.js b/addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/minimal/lib/main.js deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/minimal/lib/main.js +++ /dev/null @@ -1,8 +0,0 @@ -/* 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/. */ - -exports.main = function(options, callbacks) { - console.log("minimal"); - callbacks.quit(); -}; diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/minimal/package.json b/addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/minimal/package.json deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/minimal/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "author": "Jon Smith", - "description": "A package w/ a main module; can be built into an extension." -} diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/third_party/docs/third_party.md b/addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/third_party/docs/third_party.md deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/third_party/docs/third_party.md +++ /dev/null @@ -1,1 +0,0 @@ -hello, I'm a third party. \ No newline at end of file diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/third_party/lib/third-party.js b/addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/third_party/lib/third-party.js deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/third_party/lib/third-party.js +++ /dev/null @@ -1,8 +0,0 @@ -/* 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/. */ - -exports.main = function(options, callbacks) { - console.log("1 + 1 =", require("bar-module").add(1, 1)); - callbacks.quit(); -}; diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/third_party/package.json b/addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/third_party/package.json deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/static-files/packages/third_party/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "author": "Jon Smith", - "description": "A package w/ a main module; can be built into an extension.", - "keywords": ["potato"], - "version": "1.0", - "dependencies": ["addon-sdk", "barbeque"] -} diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/static-files/xpi-template/components/harness.js b/addon-sdk/source/python-lib/cuddlefish/tests/static-files/xpi-template/components/harness.js deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/static-files/xpi-template/components/harness.js +++ /dev/null @@ -1,8 +0,0 @@ -/* 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/. */ - -// This file contains XPCOM code that bootstraps an SDK-based add-on -// by loading its harness-options.json, registering all its resource -// directories, executing its loader, and then executing its program's -// main() function. diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/test_init.py b/addon-sdk/source/python-lib/cuddlefish/tests/test_init.py deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/test_init.py +++ /dev/null @@ -1,211 +0,0 @@ -# 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/. - -import os, unittest, shutil -import zipfile -from StringIO import StringIO -from cuddlefish import initializer -from cuddlefish.templates import TEST_MAIN_JS, PACKAGE_JSON - -tests_path = os.path.abspath(os.path.dirname(__file__)) - -class TestInit(unittest.TestCase): - - def run_init_in_subdir(self, dirname, f, *args, **kwargs): - top = os.path.abspath(os.getcwd()) - basedir = os.path.abspath(os.path.join(".test_tmp",self.id(),dirname)) - if os.path.isdir(basedir): - assert basedir.startswith(top) - shutil.rmtree(basedir) - os.makedirs(basedir) - try: - os.chdir(basedir) - return f(basedir, *args, **kwargs) - finally: - os.chdir(top) - - def do_test_init(self,basedir): - # Let's init the addon, no error admitted - f = open(".ignoreme","w") - f.write("stuff") - f.close() - - out, err = StringIO(), StringIO() - init_run = initializer(None, ["init"], out, err) - out, err = out.getvalue(), err.getvalue() - self.assertEqual(init_run["result"], 0) - self.assertTrue("* lib directory created" in out) - self.assertTrue("* data directory created" in out) - self.assertTrue("Have fun!" in out) - self.assertEqual(err,"") - self.assertTrue(len(os.listdir(basedir))>0) - main_js = os.path.join(basedir,"lib","main.js") - package_json = os.path.join(basedir,"package.json") - test_main_js = os.path.join(basedir,"test","test-main.js") - self.assertTrue(os.path.exists(main_js)) - self.assertTrue(os.path.exists(package_json)) - self.assertTrue(os.path.exists(test_main_js)) - self.assertEqual(open(main_js,"r").read(),"") - self.assertEqual(open(package_json,"r").read() % {"id":"tmp_addon_id" }, - PACKAGE_JSON % {"name":"tmp_addon_sample", - "title": "tmp_addon_SAMPLE", - "id":init_run["jid"] }) - self.assertEqual(open(test_main_js,"r").read(),TEST_MAIN_JS) - - # Let's check that the addon is initialized - out, err = StringIO(), StringIO() - init_run = initializer(None, ["init"], out, err) - out, err = out.getvalue(), err.getvalue() - self.failIfEqual(init_run["result"],0) - self.assertTrue("This command must be run in an empty directory." in err) - - def test_initializer(self): - self.run_init_in_subdir("tmp_addon_SAMPLE",self.do_test_init) - - def do_test_args(self, basedir): - # check that running it with spurious arguments will fail - out,err = StringIO(), StringIO() - init_run = initializer(None, ["init", "specified-dirname", "extra-arg"], out, err) - out, err = out.getvalue(), err.getvalue() - self.failIfEqual(init_run["result"], 0) - self.assertTrue("Too many arguments" in err) - - def test_args(self): - self.run_init_in_subdir("tmp_addon_sample", self.do_test_args) - - def _test_existing_files(self, basedir): - f = open("pay_attention_to_me","w") - f.write("stuff") - f.close() - out,err = StringIO(), StringIO() - rc = initializer(None, ["init"], out, err) - out, err = out.getvalue(), err.getvalue() - self.assertEqual(rc["result"], 1) - self.failUnless("This command must be run in an empty directory" in err, - err) - self.failIf(os.path.exists("lib")) - - def test_existing_files(self): - self.run_init_in_subdir("existing_files", self._test_existing_files) - - def test_init_subdir(self): - parent = os.path.abspath(os.path.join(".test_tmp", self.id())) - basedir = os.path.join(parent, "init-basedir") - if os.path.exists(parent): - shutil.rmtree(parent) - os.makedirs(parent) - - # if the basedir exists and is not empty, init should refuse - os.makedirs(basedir) - f = open(os.path.join(basedir, "boo"), "w") - f.write("stuff") - f.close() - out, err = StringIO(), StringIO() - rc = initializer(None, ["init", basedir], out, err) - out, err = out.getvalue(), err.getvalue() - self.assertEqual(rc["result"], 1) - self.assertTrue("testing if directory is empty" in out, out) - self.assertTrue("This command must be run in an empty directory." in err, - err) - - # a .dotfile should be tolerated - os.rename(os.path.join(basedir, "boo"), os.path.join(basedir, ".phew")) - out, err = StringIO(), StringIO() - rc = initializer(None, ["init", basedir], out, err) - out, err = out.getvalue(), err.getvalue() - self.assertEqual(rc["result"], 0) - self.assertTrue("* data directory created" in out, out) - self.assertTrue("Have fun!" in out) - self.assertEqual(err,"") - self.assertTrue(os.listdir(basedir)) - main_js = os.path.join(basedir,"lib","main.js") - package_json = os.path.join(basedir,"package.json") - self.assertTrue(os.path.exists(main_js)) - self.assertTrue(os.path.exists(package_json)) - shutil.rmtree(basedir) - - # init should create directories that don't exist already - out, err = StringIO(), StringIO() - rc = initializer(None, ["init", basedir], out, err) - out, err = out.getvalue(), err.getvalue() - self.assertEqual(rc["result"], 0) - self.assertTrue("* data directory created" in out) - self.assertTrue("Have fun!" in out) - self.assertEqual(err,"") - self.assertTrue(os.listdir(basedir)) - main_js = os.path.join(basedir,"lib","main.js") - package_json = os.path.join(basedir,"package.json") - self.assertTrue(os.path.exists(main_js)) - self.assertTrue(os.path.exists(package_json)) - - -class TestCfxQuits(unittest.TestCase): - - def run_cfx(self, addon_path, command): - old_cwd = os.getcwd() - os.chdir(addon_path) - import sys - old_stdout = sys.stdout - old_stderr = sys.stderr - sys.stdout = out = StringIO() - sys.stderr = err = StringIO() - rc = 0 - try: - import cuddlefish - args = list(command) - # Pass arguments given to cfx so that cfx can find firefox path - # if --binary option is given: - args.extend(sys.argv[1:]) - cuddlefish.run(arguments=args) - except SystemExit, e: - if "code" in e: - rc = e.code - elif "args" in e and len(e.args)>0: - rc = e.args[0] - else: - rc = 0 - finally: - sys.stdout = old_stdout - sys.stderr = old_stderr - os.chdir(old_cwd) - out.flush() - err.flush() - return rc, out.getvalue(), err.getvalue() - - # this method doesn't exists in python 2.5, - # implements our own - def assertIn(self, member, container): - """Just like self.assertTrue(a in b), but with a nicer default message.""" - if member not in container: - standardMsg = '"%s" not found in "%s"' % (member, - container) - self.fail(standardMsg) - - def test_cfx_init(self): - # Create an empty test directory - addon_path = os.path.abspath(os.path.join(".test_tmp", "test-cfx-init")) - if os.path.isdir(addon_path): - shutil.rmtree(addon_path) - os.makedirs(addon_path) - - # Fake a call to cfx init - old_cwd = os.getcwd() - os.chdir(addon_path) - out, err = StringIO(), StringIO() - rc = initializer(None, ["init"], out, err) - os.chdir(old_cwd) - out, err = out.getvalue(), err.getvalue() - self.assertEqual(rc["result"], 0) - self.assertTrue("Have fun!" in out) - self.assertEqual(err,"") - - # run cfx test - rc, out, err = self.run_cfx(addon_path, ["test"]) - self.assertEqual(rc, 0) - self.assertIn("6 of 6 tests passed.", err) - self.assertIn("Program terminated successfully.", err) - - -if __name__ == "__main__": - unittest.main() diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/test_licenses.py b/addon-sdk/source/python-lib/cuddlefish/tests/test_licenses.py deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/test_licenses.py +++ /dev/null @@ -1,100 +0,0 @@ - -# 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/. - -import unittest -import os.path - -parent = os.path.dirname -test_dir = parent(os.path.abspath(__file__)) -sdk_root = parent(parent(parent(test_dir))) - -def from_sdk_top(fn): - return os.path.abspath(os.path.join(sdk_root, fn)) - -MPL2_URL = "http://mozilla.org/MPL/2.0/" - -# These files all come with their own license headers -skip = [ - "python-lib/cuddlefish/_version.py", # generated, public domain - "doc/static-files/js/jquery.js", # MIT/GPL dual - "examples/annotator/data/jquery-1.4.2.min.js", # MIT/GPL dual - "examples/reddit-panel/data/jquery-1.4.4.min.js", # MIT/GPL dual - "examples/library-detector/data/library-detector.js", # MIT - "python-lib/mozrunner/killableprocess.py", # MIT? BSDish? - "python-lib/mozrunner/winprocess.py", # MIT - "packages/api-utils/tests/test-querystring.js", # MIT - "packages/api-utils/lib/promise.js", # MIT - "packages/api-utils/tests/test-promise.js", # MIT - "examples/actor-repl/README.md", # It's damn readme file - "examples/actor-repl/data/codemirror-compressed.js", # MIT - "examples/actor-repl/data/codemirror.css", # MIT - ] -absskip = [from_sdk_top(os.path.join(*fn.split("/"))) for fn in skip] - -class Licenses(unittest.TestCase): - def test(self): - # Examine most SDK files to check if they've got an MPL2 license - # header. We exclude some files that are known to include different - # licenses. - self.missing = [] - self.scan_file(from_sdk_top(os.path.join("python-lib", "jetpack_sdk_env.py"))) - self.scan(os.path.join("python-lib", "cuddlefish"), [".js", ".py"], - skipdirs=["sdk-docs"], # test_generate.py makes this - ) - self.scan(os.path.join("python-lib", "mozrunner"), [".py"]) - self.scan("lib", [".js", ".jsm", ".css"], - skipdirs=[ - "diffpatcher", # MIT - "method", # MIT - "child_process", # MPL 1.1/GPL 2.0/LGPL 2.1 - "fs" # MIT - ]) - self.scan("test", [".js", ".jsm", ".css", ".html"], - skipdirs=[ - "buffers", # MIT - "querystring", # MIT - "path" # MIT - ]) - self.scan("modules", [".js", ".jsm"]) - self.scan("examples", [".js", ".css", ".html", ".md"]) - self.scan("bin", [".bat", ".ps1", ".js"]) - for fn in [os.path.join("bin", "activate"), - os.path.join("bin", "cfx"), - os.path.join("bin", "integration-scripts", "buildbot-run-cfx-helper"), - os.path.join("bin", "integration-scripts", "integration-check"), - ]: - self.scan_file(from_sdk_top(fn)) - - if self.missing: - print - print "The following files are missing an MPL2 header:" - for fn in sorted(self.missing): - print " "+fn - self.fail("%d files are missing an MPL2 header" % len(self.missing)) - - def scan(self, start, extensions=[], skipdirs=[]): - # scan a whole subdirectory - start = from_sdk_top(start) - for root, dirs, files in os.walk(start): - for d in skipdirs: - if d in dirs: - dirs.remove(d) - for fn in files: - ext = os.path.splitext(fn)[1] - if extensions and ext not in extensions: - continue - absfn = os.path.join(root, fn) - if absfn in absskip: - continue - self.scan_file(absfn) - - def scan_file(self, fn): - # scan a single file - if not MPL2_URL in open(fn, "r").read(): - relfile = fn[len(sdk_root)+1:] - self.missing.append(relfile) - -if __name__ == '__main__': - unittest.main() diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/test_linker.py b/addon-sdk/source/python-lib/cuddlefish/tests/test_linker.py deleted file mode 100755 --- a/addon-sdk/source/python-lib/cuddlefish/tests/test_linker.py +++ /dev/null @@ -1,247 +0,0 @@ -# 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/. - -import os.path -import shutil -import zipfile -from StringIO import StringIO -import simplejson as json -import unittest -import cuddlefish -from cuddlefish import packaging, manifest - -def up(path, generations=1): - for i in range(generations): - path = os.path.dirname(path) - return path - -ROOT = up(os.path.abspath(__file__), 4) -def get_linker_files_dir(name): - return os.path.join(up(os.path.abspath(__file__)), "linker-files", name) - -class Basic(unittest.TestCase): - def get_pkg(self, name): - d = get_linker_files_dir(name) - return packaging.get_config_in_dir(d) - - def test_deps(self): - target_cfg = self.get_pkg("one") - pkg_cfg = packaging.build_config(ROOT, target_cfg) - deps = packaging.get_deps_for_targets(pkg_cfg, ["one"]) - self.failUnlessEqual(deps, ["one"]) - deps = packaging.get_deps_for_targets(pkg_cfg, - [target_cfg.name, "addon-sdk"]) - self.failUnlessEqual(deps, ["addon-sdk", "one"]) - - def test_manifest(self): - target_cfg = self.get_pkg("one") - pkg_cfg = packaging.build_config(ROOT, target_cfg) - deps = packaging.get_deps_for_targets(pkg_cfg, - [target_cfg.name, "addon-sdk"]) - self.failUnlessEqual(deps, ["addon-sdk", "one"]) - # target_cfg.dependencies is not provided, so we'll search through - # all known packages (everything in 'deps'). - m = manifest.build_manifest(target_cfg, pkg_cfg, deps, scan_tests=False) - m = m.get_harness_options_manifest(False) - - def assertReqIs(modname, reqname, path): - reqs = m["one/%s" % modname]["requirements"] - self.failUnlessEqual(reqs[reqname], path) - - assertReqIs("main", "sdk/panel", "sdk/panel") - assertReqIs("main", "two.js", "one/two") - assertReqIs("main", "./two", "one/two") - assertReqIs("main", "sdk/tabs.js", "sdk/tabs") - assertReqIs("main", "./subdir/three", "one/subdir/three") - assertReqIs("two", "main", "one/main") - assertReqIs("subdir/three", "../main", "one/main") - - target_cfg.dependencies = [] - - try: - # this should now work, as we ignore missing modules by default - m = manifest.build_manifest(target_cfg, pkg_cfg, deps, scan_tests=False) - m = m.get_harness_options_manifest(False) - - assertReqIs("main", "sdk/panel", "sdk/panel") - # note that with "addon-sdk" dependency present, - # "sdk/tabs.js" mapped to "sdk/tabs", but without, - # we just get the default (identity) mapping - assertReqIs("main", "sdk/tabs.js", "sdk/tabs.js") - except Exception, e: - self.fail("Must not throw from build_manifest() if modules are missing") - - # now, because .dependencies *is* provided, we won't search 'deps', - # and stop_on_missing is True, we'll get a link error - self.assertRaises(manifest.ModuleNotFoundError, - manifest.build_manifest, - target_cfg, pkg_cfg, deps, scan_tests=False, - abort_on_missing=True) - - def test_main_in_deps(self): - target_cfg = self.get_pkg("three") - package_path = [get_linker_files_dir("three-deps")] - pkg_cfg = packaging.build_config(ROOT, target_cfg, - packagepath=package_path) - deps = packaging.get_deps_for_targets(pkg_cfg, - [target_cfg.name, "addon-sdk"]) - self.failUnlessEqual(deps, ["addon-sdk", "three"]) - m = manifest.build_manifest(target_cfg, pkg_cfg, deps, scan_tests=False) - m = m.get_harness_options_manifest(False) - def assertReqIs(modname, reqname, path): - reqs = m["three/%s" % modname]["requirements"] - self.failUnlessEqual(reqs[reqname], path) - assertReqIs("main", "three-a", "three-a/main") - assertReqIs("main", "three-b", "three-b/main") - assertReqIs("main", "three-c", "three-c/main") - - def test_relative_main_in_top(self): - target_cfg = self.get_pkg("five") - package_path = [] - pkg_cfg = packaging.build_config(ROOT, target_cfg, - packagepath=package_path) - deps = packaging.get_deps_for_targets(pkg_cfg, - [target_cfg.name, "addon-sdk"]) - self.failUnlessEqual(deps, ["addon-sdk", "five"]) - # all we care about is that this next call doesn't raise an exception - m = manifest.build_manifest(target_cfg, pkg_cfg, deps, scan_tests=False) - m = m.get_harness_options_manifest(False) - reqs = m["five/main"]["requirements"] - self.failUnlessEqual(reqs, {}); - - def test_unreachable_relative_main_in_top(self): - target_cfg = self.get_pkg("six") - package_path = [] - pkg_cfg = packaging.build_config(ROOT, target_cfg, - packagepath=package_path) - deps = packaging.get_deps_for_targets(pkg_cfg, - [target_cfg.name, "addon-sdk"]) - self.failUnlessEqual(deps, ["addon-sdk", "six"]) - self.assertRaises(manifest.UnreachablePrefixError, - manifest.build_manifest, - target_cfg, pkg_cfg, deps, scan_tests=False) - - def test_unreachable_in_deps(self): - target_cfg = self.get_pkg("four") - package_path = [get_linker_files_dir("four-deps")] - pkg_cfg = packaging.build_config(ROOT, target_cfg, - packagepath=package_path) - deps = packaging.get_deps_for_targets(pkg_cfg, - [target_cfg.name, "addon-sdk"]) - self.failUnlessEqual(deps, ["addon-sdk", "four"]) - self.assertRaises(manifest.UnreachablePrefixError, - manifest.build_manifest, - target_cfg, pkg_cfg, deps, scan_tests=False) - -class Contents(unittest.TestCase): - - def run_in_subdir(self, dirname, f, *args, **kwargs): - top = os.path.abspath(os.getcwd()) - basedir = os.path.abspath(os.path.join(".test_tmp",self.id(),dirname)) - if os.path.isdir(basedir): - assert basedir.startswith(top) - shutil.rmtree(basedir) - os.makedirs(basedir) - try: - os.chdir(basedir) - return f(basedir, *args, **kwargs) - finally: - os.chdir(top) - - def assertIn(self, what, inside_what): - self.failUnless(what in inside_what, inside_what) - - def test_jetpackID(self): - # this uses "id": "jid7", to which a @jetpack should be appended - seven = get_linker_files_dir("seven") - def _test(basedir): - stdout = StringIO() - shutil.copytree(seven, "seven") - os.chdir("seven") - try: - # regrettably, run() always finishes with sys.exit() - cuddlefish.run(["xpi", "--no-strip-xpi"], - stdout=stdout) - except SystemExit, e: - self.failUnlessEqual(e.args[0], 0) - zf = zipfile.ZipFile("seven.xpi", "r") - hopts = json.loads(zf.read("harness-options.json")) - self.failUnlessEqual(hopts["jetpackID"], "jid7@jetpack") - self.run_in_subdir("x", _test) - - def test_jetpackID_suffix(self): - # this uses "id": "jid1@jetpack", so no suffix should be appended - one = get_linker_files_dir("one") - def _test(basedir): - stdout = StringIO() - shutil.copytree(one, "one") - os.chdir("one") - try: - # regrettably, run() always finishes with sys.exit() - cuddlefish.run(["xpi", "--no-strip-xpi"], - stdout=stdout) - except SystemExit, e: - self.failUnlessEqual(e.args[0], 0) - zf = zipfile.ZipFile("one.xpi", "r") - hopts = json.loads(zf.read("harness-options.json")) - self.failUnlessEqual(hopts["jetpackID"], "jid1@jetpack") - self.run_in_subdir("x", _test) - - def test_strip_default(self): - seven = get_linker_files_dir("seven") - # now run 'cfx xpi' in that directory, except put the generated .xpi - # elsewhere - def _test(basedir): - stdout = StringIO() - shutil.copytree(seven, "seven") - os.chdir("seven") - try: - # regrettably, run() always finishes with sys.exit() - cuddlefish.run(["xpi"], # --strip-xpi is now the default - stdout=stdout) - except SystemExit, e: - self.failUnlessEqual(e.args[0], 0) - zf = zipfile.ZipFile("seven.xpi", "r") - names = zf.namelist() - # problem found in bug 664840 was that an addon - # without an explicit tests/ directory would copy all files from - # the package into a bogus JID-PKGNAME-tests/ directory, so check - # for that - testfiles = [fn for fn in names if "seven/tests" in fn] - self.failUnlessEqual([], testfiles) - # another problem was that data files were being stripped from - # the XPI. Note that data/ is only supposed to be included if a - # module that actually gets used does a require("self") . - self.assertIn("resources/seven/data/text.data", - names) - self.failIf("seven/lib/unused.js" - in names, names) - self.run_in_subdir("x", _test) - - def test_no_strip(self): - seven = get_linker_files_dir("seven") - def _test(basedir): - stdout = StringIO() - shutil.copytree(seven, "seven") - os.chdir("seven") - try: - # regrettably, run() always finishes with sys.exit() - cuddlefish.run(["xpi", "--no-strip-xpi"], - stdout=stdout) - except SystemExit, e: - self.failUnlessEqual(e.args[0], 0) - zf = zipfile.ZipFile("seven.xpi", "r") - names = zf.namelist() - self.assertIn("resources/addon-sdk/lib/sdk/loader/cuddlefish.js", names) - testfiles = [fn for fn in names if "seven/tests" in fn] - self.failUnlessEqual([], testfiles) - self.assertIn("resources/seven/data/text.data", - names) - self.failUnless("resources/seven/lib/unused.js" - in names, names) - self.run_in_subdir("x", _test) - - -if __name__ == '__main__': - unittest.main() diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/test_manifest.py b/addon-sdk/source/python-lib/cuddlefish/tests/test_manifest.py deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/test_manifest.py +++ /dev/null @@ -1,256 +0,0 @@ -# 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/. - - -import unittest -from StringIO import StringIO -from cuddlefish.manifest import scan_module - -class Extra: - def failUnlessKeysAre(self, d, keys): - self.failUnlessEqual(sorted(d.keys()), sorted(keys)) - -class Require(unittest.TestCase, Extra): - def scan(self, text): - lines = StringIO(text).readlines() - requires, problems, locations = scan_module("fake.js", lines) - self.failUnlessEqual(problems, False) - return requires - - def scan_locations(self, text): - lines = StringIO(text).readlines() - requires, problems, locations = scan_module("fake.js", lines) - self.failUnlessEqual(problems, False) - return requires, locations - - def test_modules(self): - mod = """var foo = require('one');""" - requires = self.scan(mod) - self.failUnlessKeysAre(requires, ["one"]) - - mod = """var foo = require(\"one\");""" - requires = self.scan(mod) - self.failUnlessKeysAre(requires, ["one"]) - - mod = """var foo=require( 'one' ) ; """ - requires = self.scan(mod) - self.failUnlessKeysAre(requires, ["one"]) - - mod = """var foo = require('o'+'ne'); // tricky, denied""" - requires = self.scan(mod) - self.failUnlessKeysAre(requires, []) - - mod = """require('one').immediately.do().stuff();""" - requires, locations = self.scan_locations(mod) - self.failUnlessKeysAre(requires, ["one"]) - self.failUnlessEqual(locations, {"one": 1}) - - # these forms are commented out, and thus ignored - - mod = """// var foo = require('one');""" - requires = self.scan(mod) - self.failUnlessKeysAre(requires, []) - - mod = """/* var foo = require('one');""" - requires = self.scan(mod) - self.failUnlessKeysAre(requires, []) - - mod = """ * var foo = require('one');""" - requires = self.scan(mod) - self.failUnlessKeysAre(requires, []) - - mod = """ ' var foo = require('one');""" - requires = self.scan(mod) - self.failUnlessKeysAre(requires, ["one"]) - - mod = """ \" var foo = require('one');""" - requires = self.scan(mod) - self.failUnlessKeysAre(requires, ["one"]) - - # multiple requires - - mod = """const foo = require('one'); - const foo = require('two');""" - requires, locations = self.scan_locations(mod) - self.failUnlessKeysAre(requires, ["one", "two"]) - self.failUnlessEqual(locations["one"], 1) - self.failUnlessEqual(locations["two"], 2) - - mod = """const foo = require('repeated'); - const bar = require('repeated'); - const baz = require('repeated');""" - requires, locations = self.scan_locations(mod) - self.failUnlessKeysAre(requires, ["repeated"]) - self.failUnlessEqual(locations["repeated"], 1) # first occurrence - - mod = """const foo = require('one'); const foo = require('two');""" - requires = self.scan(mod) - self.failUnlessKeysAre(requires, ["one", "two"]) - - # define calls - - mod = """define('one', ['two', 'numbers/three'], function(t, th) {});""" - requires = self.scan(mod) - self.failUnlessKeysAre(requires, ["two", "numbers/three"]) - - mod = """define( - ['odd', - "numbers/four"], function() {});""" - requires = self.scan(mod) - self.failUnlessKeysAre(requires, ["odd", "numbers/four"]) - - mod = """define(function(require, exports, module) { - var a = require("some/module/a"), - b = require('b/v1'); - exports.a = a; - //This is a fakeout: require('bad'); - /* And another var bad = require('bad2'); */ - require('foo').goFoo(); - });""" - requires = self.scan(mod) - self.failUnlessKeysAre(requires, ["some/module/a", "b/v1", "foo"]) - - mod = """define ( - "foo", - ["bar"], function (bar) { - var me = require("me"); - } - )""" - requires = self.scan(mod) - self.failUnlessKeysAre(requires, ["bar", "me"]) - - mod = """define(['se' + 'ven', 'eight', nine], function () {});""" - requires = self.scan(mod) - self.failUnlessKeysAre(requires, ["eight"]) - - # async require calls - - mod = """require(['one'], function(one) {var o = require("one");});""" - requires = self.scan(mod) - self.failUnlessKeysAre(requires, ["one"]) - - mod = """require([ 'one' ], function(one) {var t = require("two");});""" - requires = self.scan(mod) - self.failUnlessKeysAre(requires, ["one", "two"]) - - mod = """require ( ['two', 'numbers/three'], function(t, th) {});""" - requires = self.scan(mod) - self.failUnlessKeysAre(requires, ["two", "numbers/three"]) - - mod = """require ( - ["bar", "fa" + 'ke' ], function (bar) { - var me = require("me"); - // require("bad").doBad(); - } - )""" - requires = self.scan(mod) - self.failUnlessKeysAre(requires, ["bar", "me"]) - -def scan2(text, fn="fake.js"): - stderr = StringIO() - lines = StringIO(text).readlines() - requires, problems, locations = scan_module(fn, lines, stderr) - stderr.seek(0) - return requires, problems, stderr.readlines() - -class Chrome(unittest.TestCase, Extra): - - def test_ignore_loader(self): - # we specifically ignore the loader itself - mod = """let {Cc,Ci} = require('chrome');""" - requires, problems, err = scan2(mod, "blah/cuddlefish.js") - self.failUnlessKeysAre(requires, ["chrome"]) - self.failUnlessEqual(problems, False) - self.failUnlessEqual(err, []) - - def test_chrome(self): - mod = """let {Cc,Ci} = require('chrome');""" - requires, problems, err = scan2(mod) - self.failUnlessKeysAre(requires, ["chrome"]) - self.failUnlessEqual(problems, False) - self.failUnlessEqual(err, []) - - mod = """var foo = require('foo'); - let {Cc,Ci} = require('chrome');""" - requires, problems, err = scan2(mod) - self.failUnlessKeysAre(requires, ["foo", "chrome"]) - self.failUnlessEqual(problems, False) - self.failUnlessEqual(err, []) - - mod = """let c = require('chrome');""" - requires, problems, err = scan2(mod) - self.failUnlessKeysAre(requires, ["chrome"]) - self.failUnlessEqual(problems, False) - self.failUnlessEqual(err, []) - - mod = """var foo = require('foo'); - let c = require('chrome');""" - requires, problems, err = scan2(mod) - self.failUnlessKeysAre(requires, ["foo", "chrome"]) - self.failUnlessEqual(problems, False) - self.failUnlessEqual(err, []) - - def test_not_chrome(self): - # from bug 596595 - mod = r'soughtLines: new RegExp("^\\s*(\\[[0-9 .]*\\])?\\s*\\(\\((EE|WW)\\)|.* [Cc]hipsets?: \\)|\\s*Backtrace")' - requires, problems, err = scan2(mod) - self.failUnlessKeysAre(requires, []) - self.failUnlessEqual((problems,err), (False, [])) - - def test_not_chrome2(self): - # from bug 655788 - mod = r"var foo = 'some stuff Cr';" - requires, problems, err = scan2(mod) - self.failUnlessKeysAre(requires, []) - self.failUnlessEqual((problems,err), (False, [])) - -class BadChrome(unittest.TestCase, Extra): - def test_bad_alias(self): - # using Components.* gets you an error, with a message that teaches - # you the correct approach. - mod = """let Cc = Components.classes; - """ - requires, problems, err = scan2(mod) - self.failUnlessKeysAre(requires, []) - self.failUnlessEqual(problems, True) - self.failUnlessEqual(err[1], "The following lines from file fake.js:\n") - self.failUnlessEqual(err[2], " 1: let Cc = Components.classes;\n") - self.failUnlessEqual(err[3], " 2: let Cu = Components.utils;\n") - self.failUnlessEqual(err[4], "use 'Components' to access chrome authority. To do so, you need to add a\n") - self.failUnlessEqual(err[5], "line somewhat like the following:\n") - self.failUnlessEqual(err[7], ' const {Cc,Cu} = require("chrome");\n') - self.failUnlessEqual(err[9], "Then you can use any shortcuts to its properties that you import from the\n") - - def test_bad_misc(self): - # If it looks like you're using something that doesn't have an alias, - # the warning also suggests a better way. - mod = """if (Components.isSuccessCode(foo)) - """ - requires, problems, err = scan2(mod) - self.failUnlessKeysAre(requires, []) - self.failUnlessEqual(problems, True) - self.failUnlessEqual(err[1], "The following lines from file fake.js:\n") - self.failUnlessEqual(err[2], " 1: if (Components.isSuccessCode(foo))\n") - self.failUnlessEqual(err[3], "use 'Components' to access chrome authority. To do so, you need to add a\n") - self.failUnlessEqual(err[4], "line somewhat like the following:\n") - self.failUnlessEqual(err[6], ' const {components} = require("chrome");\n') - self.failUnlessEqual(err[8], "Then you can use any shortcuts to its properties that you import from the\n") - - def test_chrome_components(self): - # Bug 636145/774636: We no longer tolerate usages of "Components", - # even when adding `require("chrome")` to your module. - mod = """require("chrome"); - var ios = Components.classes['@mozilla.org/network/io-service;1'];""" - requires, problems, err = scan2(mod) - self.failUnlessKeysAre(requires, ["chrome"]) - self.failUnlessEqual(problems, True) - self.failUnlessEqual(err[1], "The following lines from file fake.js:\n") - self.failUnlessEqual(err[2], " 2: var ios = Components.classes['@mozilla.org/network/io-service;1'];\n") - self.failUnlessEqual(err[3], "use 'Components' to access chrome authority. To do so, you need to add a\n") - self.failUnlessEqual(err[4], "line somewhat like the following:\n") - self.failUnlessEqual(err[6], ' const {Cc} = require("chrome");\n') - self.failUnlessEqual(err[8], "Then you can use any shortcuts to its properties that you import from the\n") - -if __name__ == '__main__': - unittest.main() diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/test_packaging.py b/addon-sdk/source/python-lib/cuddlefish/tests/test_packaging.py deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/test_packaging.py +++ /dev/null @@ -1,117 +0,0 @@ -# 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/. - -import os -import unittest - -from cuddlefish import packaging -from cuddlefish.bunch import Bunch - -tests_path = os.path.abspath(os.path.dirname(__file__)) -static_files_path = os.path.join(tests_path, 'static-files') - -def get_configs(pkg_name, dirname='static-files'): - root_path = os.path.join(tests_path, dirname) - pkg_path = os.path.join(root_path, 'packages', pkg_name) - if not (os.path.exists(pkg_path) and os.path.isdir(pkg_path)): - raise Exception('path does not exist: %s' % pkg_path) - target_cfg = packaging.get_config_in_dir(pkg_path) - pkg_cfg = packaging.build_config(root_path, target_cfg) - deps = packaging.get_deps_for_targets(pkg_cfg, [pkg_name]) - build = packaging.generate_build_for_target( - pkg_cfg=pkg_cfg, - target=pkg_name, - deps=deps, - is_running_tests=True, - ) - return Bunch(target_cfg=target_cfg, pkg_cfg=pkg_cfg, build=build) - -class PackagingTests(unittest.TestCase): - def test_bug_588661(self): - configs = get_configs('foo', 'bug-588661-files') - self.assertEqual(configs.build.loader, - 'foo/lib/foo-loader.js') - - def test_bug_614712(self): - configs = get_configs('commonjs-naming', 'bug-614712-files') - packages = configs.pkg_cfg.packages - base = os.path.join(tests_path, 'bug-614712-files', 'packages') - self.assertEqual(packages['original-naming'].tests, - [os.path.join(base, 'original-naming', 'tests')]) - self.assertEqual(packages['commonjs-naming'].tests, - [os.path.join(base, 'commonjs-naming', 'test')]) - - def test_basic(self): - configs = get_configs('aardvark') - packages = configs.pkg_cfg.packages - - self.assertTrue('addon-sdk' in packages) - self.assertTrue('aardvark' in packages) - self.assertTrue('addon-sdk' in packages.aardvark.dependencies) - self.assertEqual(packages['addon-sdk'].loader, 'lib/sdk/loader/cuddlefish.js') - self.assertTrue(packages.aardvark.main == 'main') - self.assertTrue(packages.aardvark.version == "1.0") - -class PackagePath(unittest.TestCase): - def test_packagepath(self): - root_path = os.path.join(tests_path, 'static-files') - pkg_path = os.path.join(root_path, 'packages', 'minimal') - target_cfg = packaging.get_config_in_dir(pkg_path) - pkg_cfg = packaging.build_config(root_path, target_cfg) - base_packages = set(pkg_cfg.packages.keys()) - ppath = [os.path.join(tests_path, 'bug-611495-files')] - pkg_cfg2 = packaging.build_config(root_path, target_cfg, packagepath=ppath) - all_packages = set(pkg_cfg2.packages.keys()) - self.assertEqual(sorted(["jspath-one"]), - sorted(all_packages - base_packages)) - -class Directories(unittest.TestCase): - # for bug 652227 - packages_path = os.path.join(tests_path, "bug-652227-files", "packages") - def get_config(self, pkg_name): - pkg_path = os.path.join(tests_path, "bug-652227-files", "packages", - pkg_name) - return packaging.get_config_in_dir(pkg_path) - - def test_explicit_lib(self): - # package.json provides .lib - p = self.get_config('explicit-lib') - self.assertEqual(os.path.abspath(p.lib[0]), - os.path.abspath(os.path.join(self.packages_path, - "explicit-lib", - "alt2-lib"))) - - def test_directories_lib(self): - # package.json provides .directories.lib - p = self.get_config('explicit-dir-lib') - self.assertEqual(os.path.abspath(p.lib[0]), - os.path.abspath(os.path.join(self.packages_path, - "explicit-dir-lib", - "alt-lib"))) - - def test_lib(self): - # package.json is empty, but lib/ exists - p = self.get_config("default-lib") - self.assertEqual(os.path.abspath(p.lib[0]), - os.path.abspath(os.path.join(self.packages_path, - "default-lib", - "lib"))) - - def test_root(self): - # package.json is empty, no lib/, so files are in root - p = self.get_config('default-root') - self.assertEqual(os.path.abspath(p.lib[0]), - os.path.abspath(os.path.join(self.packages_path, - "default-root"))) - - def test_locale(self): - # package.json is empty, but locale/ exists and should be used - p = self.get_config("default-locale") - self.assertEqual(os.path.abspath(p.locale), - os.path.abspath(os.path.join(self.packages_path, - "default-locale", - "locale"))) - -if __name__ == "__main__": - unittest.main() diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/test_preflight.py b/addon-sdk/source/python-lib/cuddlefish/tests/test_preflight.py deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/test_preflight.py +++ /dev/null @@ -1,147 +0,0 @@ -# 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/. - - -import os, shutil -import simplejson as json -import unittest -import hashlib -import base64 -from cuddlefish import preflight -from StringIO import StringIO - -class Util(unittest.TestCase): - def get_basedir(self): - return os.path.join(".test_tmp", self.id()) - def make_basedir(self): - basedir = self.get_basedir() - if os.path.isdir(basedir): - here = os.path.abspath(os.getcwd()) - assert os.path.abspath(basedir).startswith(here) # safety - shutil.rmtree(basedir) - os.makedirs(basedir) - return basedir - - def test_base62(self): - for i in range(1000): - h = hashlib.sha1(str(i)).digest() - s1 = base64.b64encode(h, "AB").strip("=") - s2 = base64.b64encode(h).strip("=").replace("+","A").replace("/","B") - self.failUnlessEqual(s1, s2) - - def write(self, config): - basedir = self.get_basedir() - fn = os.path.join(basedir, "package.json") - open(fn,"w").write(config) - def read(self): - basedir = self.get_basedir() - fn = os.path.join(basedir, "package.json") - return open(fn,"r").read() - - def get_cfg(self): - cfg = json.loads(self.read()) - if "name" not in cfg: - # the cfx parser always provides a name, even if package.json - # doesn't contain one - cfg["name"] = "pretend name" - return cfg - - def parse(self, keydata): - fields = {} - fieldnames = [] - for line in keydata.split("\n"): - if line.strip(): - k,v = line.split(":", 1) - k = k.strip() ; v = v.strip() - fields[k] = v - fieldnames.append(k) - return fields, fieldnames - - def test_preflight(self): - basedir = self.make_basedir() - fn = os.path.join(basedir, "package.json") - - # empty config is not ok: need id (name is automatically supplied) - config_orig = "{}" - self.write(config_orig) - out = StringIO() - cfg = self.get_cfg() - config_was_ok, modified = preflight.preflight_config(cfg, fn, - stderr=out) - self.failUnlessEqual(config_was_ok, False) - self.failUnlessEqual(modified, True) - backup_fn = os.path.join(basedir, "package.json.backup") - config_backup = open(backup_fn,"r").read() - self.failUnlessEqual(config_backup, config_orig) - config = json.loads(self.read()) - self.failIf("name" in config) - self.failUnless("id" in config) - self.failUnless(config["id"].startswith("jid1-"), config["id"]) - self.failUnlessEqual(out.getvalue().strip(), - "No 'id' in package.json: creating a new ID for you.") - os.unlink(backup_fn) - - # just a name? we add the id - config_orig = '{"name": "my-awesome-package"}' - self.write(config_orig) - out = StringIO() - cfg = self.get_cfg() - config_was_ok, modified = preflight.preflight_config(cfg, fn, - stderr=out) - self.failUnlessEqual(config_was_ok, False) - self.failUnlessEqual(modified, True) - backup_fn = os.path.join(basedir, "package.json.backup") - config_backup = open(backup_fn,"r").read() - self.failUnlessEqual(config_backup, config_orig) - config = json.loads(self.read()) - self.failUnlessEqual(config["name"], "my-awesome-package") - self.failUnless("id" in config) - self.failUnless(config["id"].startswith("jid1-"), config["id"]) - jid = str(config["id"]) - self.failUnlessEqual(out.getvalue().strip(), - "No 'id' in package.json: creating a new ID for you.") - os.unlink(backup_fn) - - # name and valid id? great! ship it! - config2 = '{"name": "my-awesome-package", "id": "%s"}' % jid - self.write(config2) - out = StringIO() - cfg = self.get_cfg() - config_was_ok, modified = preflight.preflight_config(cfg, fn, - stderr=out) - self.failUnlessEqual(config_was_ok, True) - self.failUnlessEqual(modified, False) - config2a = self.read() - self.failUnlessEqual(config2a, config2) - self.failUnlessEqual(out.getvalue().strip(), "") - - # name and anonymous ID? without asking to see its papers, ship it - config3 = '{"name": "my-old-skool-package", "id": "anonid0-deadbeef"}' - self.write(config3) - out = StringIO() - cfg = self.get_cfg() - config_was_ok, modified = preflight.preflight_config(cfg, fn, - stderr=out) - self.failUnlessEqual(config_was_ok, True) - self.failUnlessEqual(modified, False) - config3a = self.read() - self.failUnlessEqual(config3a, config3) - self.failUnlessEqual(out.getvalue().strip(), "") - - # name and old-style ID? with nostalgic trepidation, ship it - config4 = '{"name": "my-old-skool-package", "id": "foo@bar.baz"}' - self.write(config4) - out = StringIO() - cfg = self.get_cfg() - config_was_ok, modified = preflight.preflight_config(cfg, fn, - stderr=out) - self.failUnlessEqual(config_was_ok, True) - self.failUnlessEqual(modified, False) - config4a = self.read() - self.failUnlessEqual(config4a, config4) - self.failUnlessEqual(out.getvalue().strip(), "") - - -if __name__ == '__main__': - unittest.main() diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/test_property_parser.py b/addon-sdk/source/python-lib/cuddlefish/tests/test_property_parser.py deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/test_property_parser.py +++ /dev/null @@ -1,93 +0,0 @@ -# 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/. - -import unittest - -from cuddlefish.property_parser import parse, MalformedLocaleFileError - -class TestParser(unittest.TestCase): - - def test_parse(self): - lines = [ - # Comments are striped only if `#` is the first non-space character - "sharp=#can be in value", - "# comment", - "#key=value", - " # comment2", - - "keyWithNoValue=", - "valueWithSpaces= ", - "valueWithMultilineSpaces= \\", - " \\", - " ", - - # All spaces before/after are striped - " key = value ", - "key2=value2", - # Keys can contain '%' - "%s key=%s value", - - # Accept empty lines - "", - " ", - - # Multiline string must use backslash at end of lines - "multi=line\\", "value", - # With multiline string, left spaces are stripped ... - "some= spaces\\", " are\\ ", " stripped ", - # ... but not right spaces, except the last line! - "but=not \\", "all of \\", " them ", - - # Explicit [other] plural definition - "explicitPlural[one] = one", - "explicitPlural[other] = other", - - # Implicit [other] plural definition - "implicitPlural[one] = one", - "implicitPlural = other", # This key is the [other] one - ] - # Ensure that all lines end with a `\n` - # And that strings are unicode ones (parser code relies on it) - lines = [unicode(l + "\n") for l in lines] - pairs = parse(lines) - expected = { - "sharp": "#can be in value", - - "key": "value", - "key2": "value2", - "%s key": "%s value", - - "keyWithNoValue": "", - "valueWithSpaces": "", - "valueWithMultilineSpaces": "", - - "multi": "linevalue", - "some": "spacesarestripped", - "but": "not all of them", - - "implicitPlural": { - "one": "one", - "other": "other" - }, - "explicitPlural": { - "one": "one", - "other": "other" - }, - } - self.assertEqual(pairs, expected) - - def test_exceptions(self): - self.failUnlessRaises(MalformedLocaleFileError, parse, - ["invalid line with no key value"]) - self.failUnlessRaises(MalformedLocaleFileError, parse, - ["plural[one]=plural with no [other] value"]) - self.failUnlessRaises(MalformedLocaleFileError, parse, - ["multiline with no last empty line=\\"]) - self.failUnlessRaises(MalformedLocaleFileError, parse, - ["=no key"]) - self.failUnlessRaises(MalformedLocaleFileError, parse, - [" =only spaces in key"]) - -if __name__ == "__main__": - unittest.main() diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/test_rdf.py b/addon-sdk/source/python-lib/cuddlefish/tests/test_rdf.py deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/test_rdf.py +++ /dev/null @@ -1,54 +0,0 @@ -# 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/. - -import unittest -import xml.dom.minidom -import os.path - -from cuddlefish import rdf, packaging - -parent = os.path.dirname -test_dir = parent(os.path.abspath(__file__)) -template_dir = os.path.join(parent(test_dir), "../../app-extension") - -class RDFTests(unittest.TestCase): - def testBug567660(self): - obj = rdf.RDF() - data = u'\u2026'.encode('utf-8') - x = '%s' % data - obj.dom = xml.dom.minidom.parseString(x) - self.assertEqual(obj.dom.documentElement.firstChild.nodeValue, - u'\u2026') - self.assertEqual(str(obj).replace("\n",""), x.replace("\n","")) - - def failUnlessIn(self, substring, s, msg=""): - if substring not in s: - self.fail("(%s) substring '%s' not in string '%s'" - % (msg, substring, s)) - - def testUnpack(self): - basedir = os.path.join(test_dir, "bug-715340-files") - for n in ["pkg-1-pack", "pkg-2-unpack", "pkg-3-pack"]: - cfg = packaging.get_config_in_dir(os.path.join(basedir, n)) - m = rdf.gen_manifest(template_dir, cfg, jid="JID") - if n.endswith("-pack"): - # these ones should remain packed - self.failUnlessEqual(m.get("em:unpack"), "false") - self.failUnlessIn("false", str(m), n) - else: - # and these should be unpacked - self.failUnlessEqual(m.get("em:unpack"), "true") - self.failUnlessIn("true", str(m), n) - - def testTitle(self): - basedir = os.path.join(test_dir, 'bug-906359-files') - for n in ['title', 'fullName', 'none']: - cfg = packaging.get_config_in_dir(os.path.join(basedir, n)) - m = rdf.gen_manifest(template_dir, cfg, jid='JID') - self.failUnlessEqual(m.get('em:name'), 'a long ' + n) - self.failUnlessIn('a long ' + n + '', str(m), n) - - -if __name__ == '__main__': - unittest.main() diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/test_runner.py b/addon-sdk/source/python-lib/cuddlefish/tests/test_runner.py deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/test_runner.py +++ /dev/null @@ -1,27 +0,0 @@ -# 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/. - - -def xulrunner_app_runner_doctests(): - """ - >>> import sys - >>> from cuddlefish import runner - >>> runner.XulrunnerAppRunner(binary='foo') - Traceback (most recent call last): - ... - Exception: Binary path does not exist foo - - >>> runner.XulrunnerAppRunner(binary=sys.executable) - Traceback (most recent call last): - ... - ValueError: application.ini not found in cmdargs - - >>> runner.XulrunnerAppRunner(binary=sys.executable, - ... cmdargs=['application.ini']) - Traceback (most recent call last): - ... - ValueError: file does not exist: 'application.ini' - """ - - pass diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/test_util.py b/addon-sdk/source/python-lib/cuddlefish/tests/test_util.py deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/test_util.py +++ /dev/null @@ -1,22 +0,0 @@ -# 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/. - - -import unittest -from cuddlefish.manifest import filter_filenames, filter_dirnames - -class Filter(unittest.TestCase): - def test_filter_filenames(self): - names = ["foo", "bar.js", "image.png", - ".hidden", "foo~", ".foo.swp", "bar.js.swp"] - self.failUnlessEqual(sorted(filter_filenames(names)), - sorted(["foo", "bar.js", "image.png"])) - - def test_filter_dirnames(self): - names = ["subdir", "data", ".git", ".hg", ".svn", "defaults"] - self.failUnlessEqual(sorted(filter_dirnames(names)), - sorted(["subdir", "data", "defaults"])) - -if __name__ == '__main__': - unittest.main() diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/test_version.py b/addon-sdk/source/python-lib/cuddlefish/tests/test_version.py deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/test_version.py +++ /dev/null @@ -1,28 +0,0 @@ -# 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/. - -import os -import unittest -import shutil - -from cuddlefish._version import get_versions - -class Version(unittest.TestCase): - def get_basedir(self): - return os.path.join(".test_tmp", self.id()) - def make_basedir(self): - basedir = self.get_basedir() - if os.path.isdir(basedir): - here = os.path.abspath(os.getcwd()) - assert os.path.abspath(basedir).startswith(here) # safety - shutil.rmtree(basedir) - os.makedirs(basedir) - return basedir - - def test_current_version(self): - # the SDK should be able to determine its own version. We don't care - # what it is, merely that it can be computed. - version = get_versions()["version"] - self.failUnless(isinstance(version, str), (version, type(version))) - self.failUnless(len(version) > 0, version) diff --git a/addon-sdk/source/python-lib/cuddlefish/tests/test_xpi.py b/addon-sdk/source/python-lib/cuddlefish/tests/test_xpi.py deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/tests/test_xpi.py +++ /dev/null @@ -1,310 +0,0 @@ -# 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/. - -import os -import unittest -import zipfile -import pprint -import shutil - -import simplejson as json -from cuddlefish import xpi, packaging, manifest, buildJID -from cuddlefish.tests import test_packaging -from test_linker import up - -import xml.etree.ElementTree as ElementTree - -xpi_template_path = os.path.join(test_packaging.static_files_path, - 'xpi-template') - -fake_manifest = '' - - -class Bug588119Tests(unittest.TestCase): - def makexpi(self, pkg_name): - self.xpiname = "%s.xpi" % pkg_name - create_xpi(self.xpiname, pkg_name, 'bug-588119-files') - self.xpi = zipfile.ZipFile(self.xpiname, 'r') - options = self.xpi.read('harness-options.json') - self.xpi_harness_options = json.loads(options) - - def setUp(self): - self.xpiname = None - self.xpi = None - - def tearDown(self): - if self.xpi: - self.xpi.close() - if self.xpiname and os.path.exists(self.xpiname): - os.remove(self.xpiname) - - def testPackageWithImplicitIcon(self): - self.makexpi('implicit-icon') - assert 'icon.png' in self.xpi.namelist() - - def testPackageWithImplicitIcon64(self): - self.makexpi('implicit-icon') - assert 'icon64.png' in self.xpi.namelist() - - def testPackageWithExplicitIcon(self): - self.makexpi('explicit-icon') - assert 'icon.png' in self.xpi.namelist() - - def testPackageWithExplicitIcon64(self): - self.makexpi('explicit-icon') - assert 'icon64.png' in self.xpi.namelist() - - def testPackageWithNoIcon(self): - self.makexpi('no-icon') - assert 'icon.png' not in self.xpi.namelist() - - def testIconPathNotInHarnessOptions(self): - self.makexpi('implicit-icon') - assert 'icon' not in self.xpi_harness_options - - def testIcon64PathNotInHarnessOptions(self): - self.makexpi('implicit-icon') - assert 'icon64' not in self.xpi_harness_options - -class ExtraHarnessOptions(unittest.TestCase): - def setUp(self): - self.xpiname = None - self.xpi = None - - def tearDown(self): - if self.xpi: - self.xpi.close() - if self.xpiname and os.path.exists(self.xpiname): - os.remove(self.xpiname) - - def testOptions(self): - pkg_name = "extra-options" - self.xpiname = "%s.xpi" % pkg_name - create_xpi(self.xpiname, pkg_name, "bug-669274-files", - extra_harness_options={"builderVersion": "futuristic"}) - self.xpi = zipfile.ZipFile(self.xpiname, 'r') - options = self.xpi.read('harness-options.json') - hopts = json.loads(options) - self.failUnless("builderVersion" in hopts) - self.failUnlessEqual(hopts["builderVersion"], "futuristic") - - def testBadOptionName(self): - pkg_name = "extra-options" - self.xpiname = "%s.xpi" % pkg_name - self.failUnlessRaises(xpi.HarnessOptionAlreadyDefinedError, - create_xpi, - self.xpiname, pkg_name, "bug-669274-files", - extra_harness_options={"main": "already in use"}) - -class SmallXPI(unittest.TestCase): - def setUp(self): - self.root = up(os.path.abspath(__file__), 4) - def get_linker_files_dir(self, name): - return os.path.join(up(os.path.abspath(__file__)), "linker-files", name) - def get_pkg(self, name): - d = self.get_linker_files_dir(name) - return packaging.get_config_in_dir(d) - - def get_basedir(self): - return os.path.join(".test_tmp", self.id()) - def make_basedir(self): - basedir = self.get_basedir() - if os.path.isdir(basedir): - here = os.path.abspath(os.getcwd()) - assert os.path.abspath(basedir).startswith(here) # safety - shutil.rmtree(basedir) - os.makedirs(basedir) - return basedir - - def test_contents(self): - target_cfg = self.get_pkg("three") - package_path = [self.get_linker_files_dir("three-deps")] - pkg_cfg = packaging.build_config(self.root, target_cfg, - packagepath=package_path) - deps = packaging.get_deps_for_targets(pkg_cfg, - [target_cfg.name, "addon-sdk"]) - addon_sdk_dir = pkg_cfg.packages["addon-sdk"].lib[0] - m = manifest.build_manifest(target_cfg, pkg_cfg, deps, scan_tests=False) - used_files = list(m.get_used_files(True)) - here = up(os.path.abspath(__file__)) - def absify(*parts): - fn = os.path.join(here, "linker-files", *parts) - return os.path.abspath(fn) - expected = [absify(*parts) for parts in - [("three", "lib", "main.js"), - ("three-deps", "three-a", "lib", "main.js"), - ("three-deps", "three-a", "lib", "subdir", "subfile.js"), - ("three", "data", "msg.txt"), - ("three", "data", "subdir", "submsg.txt"), - ("three-deps", "three-b", "lib", "main.js"), - ("three-deps", "three-c", "lib", "main.js"), - ("three-deps", "three-c", "lib", "sub", "foo.js") - ]] - - add_addon_sdk= lambda path: os.path.join(addon_sdk_dir, path) - expected.extend([add_addon_sdk(module) for module in [ - os.path.join("sdk", "self.js"), - os.path.join("sdk", "core", "promise.js"), - os.path.join("sdk", "net", "url.js"), - os.path.join("sdk", "util", "object.js"), - os.path.join("sdk", "util", "array.js"), - os.path.join("sdk", "preferences", "service.js") - ]]) - - missing = set(expected) - set(used_files) - extra = set(used_files) - set(expected) - self.failUnlessEqual(list(missing), []) - self.failUnlessEqual(list(extra), []) - used_deps = m.get_used_packages() - - build = packaging.generate_build_for_target(pkg_cfg, target_cfg.name, - used_deps, - include_tests=False) - options = {'main': target_cfg.main} - options.update(build) - basedir = self.make_basedir() - xpi_name = os.path.join(basedir, "contents.xpi") - xpi.build_xpi(template_root_dir=xpi_template_path, - manifest=fake_manifest, - xpi_path=xpi_name, - harness_options=options, - limit_to=used_files) - x = zipfile.ZipFile(xpi_name, "r") - names = x.namelist() - expected = ["components/", - "components/harness.js", - # the real template also has 'bootstrap.js', but the fake - # one in tests/static-files/xpi-template doesn't - "harness-options.json", - "install.rdf", - "resources/", - "resources/addon-sdk/", - "resources/addon-sdk/lib/", - "resources/addon-sdk/lib/sdk/", - "resources/addon-sdk/lib/sdk/self.js", - "resources/addon-sdk/lib/sdk/core/", - "resources/addon-sdk/lib/sdk/util/", - "resources/addon-sdk/lib/sdk/net/", - "resources/addon-sdk/lib/sdk/core/promise.js", - "resources/addon-sdk/lib/sdk/util/object.js", - "resources/addon-sdk/lib/sdk/util/array.js", - "resources/addon-sdk/lib/sdk/net/url.js", - "resources/addon-sdk/lib/sdk/preferences/", - "resources/addon-sdk/lib/sdk/preferences/service.js", - "resources/three/", - "resources/three/lib/", - "resources/three/lib/main.js", - "resources/three/data/", - "resources/three/data/msg.txt", - "resources/three/data/subdir/", - "resources/three/data/subdir/submsg.txt", - "resources/three-a/", - "resources/three-a/lib/", - "resources/three-a/lib/main.js", - "resources/three-a/lib/subdir/", - "resources/three-a/lib/subdir/subfile.js", - "resources/three-b/", - "resources/three-b/lib/", - "resources/three-b/lib/main.js", - "resources/three-c/", - "resources/three-c/lib/", - "resources/three-c/lib/main.js", - "resources/three-c/lib/sub/", - "resources/three-c/lib/sub/foo.js", - # notably absent: three-a/lib/unused.js - "locale/", - "locale/fr-FR.json", - "locales.json", - ] - # showing deltas makes failures easier to investigate - missing = set(expected) - set(names) - extra = set(names) - set(expected) - self.failUnlessEqual((list(missing), list(extra)), ([], [])) - self.failUnlessEqual(sorted(names), sorted(expected)) - - # check locale files - localedata = json.loads(x.read("locales.json")) - self.failUnlessEqual(sorted(localedata["locales"]), sorted(["fr-FR"])) - content = x.read("locale/fr-FR.json") - locales = json.loads(content) - # Locale files are merged into one. - # Conflicts are silently resolved by taking last package translation, - # so that we get "No" translation from three-c instead of three-b one. - self.failUnlessEqual(locales, json.loads(u''' - { - "No": "Nein", - "one": "un", - "What?": "Quoi?", - "Yes": "Oui", - "plural": { - "other": "other", - "one": "one" - }, - "uft8_value": "\u00e9" - }''')) - - -def document_dir(name): - if name in ['packages', 'xpi-template']: - dirname = os.path.join(test_packaging.static_files_path, name) - document_dir_files(dirname) - elif name == 'xpi-output': - create_xpi('test-xpi.xpi') - document_zip_file('test-xpi.xpi') - os.remove('test-xpi.xpi') - else: - raise Exception('unknown dir: %s' % name) - -def normpath(path): - """ - Make a platform-specific relative path use '/' as a separator. - """ - - return path.replace(os.path.sep, '/') - -def document_zip_file(path): - zip = zipfile.ZipFile(path, 'r') - for name in sorted(zip.namelist()): - contents = zip.read(name) - lines = contents.splitlines() - if len(lines) == 1 and name.endswith('.json') and len(lines[0]) > 75: - # Ideally we would json-decode this, but it results - # in an annoying 'u' before every string literal, - # since json decoding makes all strings unicode. - contents = eval(contents) - contents = pprint.pformat(contents) - lines = contents.splitlines() - contents = "\n ".join(lines) - print "%s:\n %s" % (normpath(name), contents) - zip.close() - -def document_dir_files(path): - filename_contents_tuples = [] - for dirpath, dirnames, filenames in os.walk(path): - relpath = dirpath[len(path)+1:] - for filename in filenames: - abspath = os.path.join(dirpath, filename) - contents = open(abspath, 'r').read() - contents = "\n ".join(contents.splitlines()) - relfilename = os.path.join(relpath, filename) - filename_contents_tuples.append((normpath(relfilename), contents)) - filename_contents_tuples.sort() - for filename, contents in filename_contents_tuples: - print "%s:" % filename - print " %s" % contents - -def create_xpi(xpiname, pkg_name='aardvark', dirname='static-files', - extra_harness_options={}): - configs = test_packaging.get_configs(pkg_name, dirname) - options = {'main': configs.target_cfg.main, - 'jetpackID': buildJID(configs.target_cfg), } - options.update(configs.build) - xpi.build_xpi(template_root_dir=xpi_template_path, - manifest=fake_manifest, - xpi_path=xpiname, - harness_options=options, - extra_harness_options=extra_harness_options) - -if __name__ == '__main__': - unittest.main() diff --git a/addon-sdk/source/python-lib/cuddlefish/util.py b/addon-sdk/source/python-lib/cuddlefish/util.py deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/util.py +++ /dev/null @@ -1,23 +0,0 @@ -# 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/. - - -IGNORED_FILE_PREFIXES = ["."] -IGNORED_FILE_SUFFIXES = ["~", ".swp"] -IGNORED_DIRS = [".git", ".svn", ".hg"] - -def filter_filenames(filenames, ignored_files=[".hgignore"]): - for filename in filenames: - if filename in ignored_files: - continue - if any([filename.startswith(suffix) - for suffix in IGNORED_FILE_PREFIXES]): - continue - if any([filename.endswith(suffix) - for suffix in IGNORED_FILE_SUFFIXES]): - continue - yield filename - -def filter_dirnames(dirnames): - return [dirname for dirname in dirnames if dirname not in IGNORED_DIRS] diff --git a/addon-sdk/source/python-lib/cuddlefish/version_comparator.py b/addon-sdk/source/python-lib/cuddlefish/version_comparator.py deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/version_comparator.py +++ /dev/null @@ -1,206 +0,0 @@ -# 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/. - -''' - This is a really crummy, slow Python implementation of the Mozilla - platform's nsIVersionComparator interface: - - https://developer.mozilla.org/En/NsIVersionComparator - - For more information, also see: - - http://dxr.mozilla.org/mozilla-central/source/xpcom/glue/nsVersionComparator.cpp -''' - -import re -import sys - -class VersionPart(object): - ''' - Examples: - - >>> VersionPart('1') - (1, None, 0, None) - - >>> VersionPart('1pre') - (1, 'pre', 0, None) - - >>> VersionPart('1pre10') - (1, 'pre', 10, None) - - >>> VersionPart('1pre10a') - (1, 'pre', 10, 'a') - - >>> VersionPart('1+') - (2, 'pre', 0, None) - - >>> VersionPart('*').numA == sys.maxint - True - - >>> VersionPart('1') < VersionPart('2') - True - - >>> VersionPart('2') > VersionPart('1') - True - - >>> VersionPart('1') == VersionPart('1') - True - - >>> VersionPart('1pre') > VersionPart('1') - False - - >>> VersionPart('1') < VersionPart('1pre') - False - - >>> VersionPart('1pre1') < VersionPart('1pre2') - True - - >>> VersionPart('1pre10b') > VersionPart('1pre10a') - True - - >>> VersionPart('1pre10b') == VersionPart('1pre10b') - True - - >>> VersionPart('1pre10a') < VersionPart('1pre10b') - True - - >>> VersionPart('1') > VersionPart('') - True - ''' - - _int_part = re.compile('[+-]?(\d*)(.*)') - _num_chars = '0123456789+-' - - def __init__(self, part): - self.numA = 0 - self.strB = None - self.numC = 0 - self.extraD = None - - if not part: - return - - if part == '*': - self.numA = sys.maxint - else: - match = self._int_part.match(part) - self.numA = int(match.group(1)) - self.strB = match.group(2) or None - if self.strB == '+': - self.strB = 'pre' - self.numA += 1 - elif self.strB: - i = 0 - num_found = -1 - for char in self.strB: - if char in self._num_chars: - num_found = i - break - i += 1 - if num_found != -1: - match = self._int_part.match(self.strB[num_found:]) - self.numC = int(match.group(1)) - self.extraD = match.group(2) or None - self.strB = self.strB[:num_found] - - def _strcmp(self, str1, str2): - # Any string is *before* no string. - if str1 is None: - if str2 is None: - return 0 - else: - return 1 - - if str2 is None: - return -1 - - return cmp(str1, str2) - - def __cmp__(self, other): - r = cmp(self.numA, other.numA) - if r: - return r - - r = self._strcmp(self.strB, other.strB) - if r: - return r - - r = cmp(self.numC, other.numC) - if r: - return r - - return self._strcmp(self.extraD, other.extraD) - - def __repr__(self): - return repr((self.numA, self.strB, self.numC, self.extraD)) - -def compare(a, b): - ''' - Examples: - - >>> compare('1', '2') - -1 - - >>> compare('1', '1') - 0 - - >>> compare('2', '1') - 1 - - >>> compare('1.0pre1', '1.0pre2') - -1 - - >>> compare('1.0pre2', '1.0') - -1 - - >>> compare('1.0', '1.0.0') - 0 - - >>> compare('1.0.0', '1.0.0.0') - 0 - - >>> compare('1.0.0.0', '1.1pre') - -1 - - >>> compare('1.1pre', '1.1pre0') - 0 - - >>> compare('1.1pre0', '1.0+') - 0 - - >>> compare('1.0+', '1.1pre1a') - -1 - - >>> compare('1.1pre1a', '1.1pre1') - -1 - - >>> compare('1.1pre1', '1.1pre10a') - -1 - - >>> compare('1.1pre10a', '1.1pre10') - -1 - - >>> compare('1.1pre10a', '1.*') - -1 - ''' - - a_parts = a.split('.') - b_parts = b.split('.') - - if len(a_parts) < len(b_parts): - a_parts.extend([''] * (len(b_parts) - len(a_parts))) - else: - b_parts.extend([''] * (len(a_parts) - len(b_parts))) - - for a_part, b_part in zip(a_parts, b_parts): - r = cmp(VersionPart(a_part), VersionPart(b_part)) - if r: - return r - - return 0 - -if __name__ == '__main__': - import doctest - - doctest.testmod(verbose=True) diff --git a/addon-sdk/source/python-lib/cuddlefish/xpi.py b/addon-sdk/source/python-lib/cuddlefish/xpi.py deleted file mode 100644 --- a/addon-sdk/source/python-lib/cuddlefish/xpi.py +++ /dev/null @@ -1,169 +0,0 @@ -# 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/. - -import os -import zipfile -import simplejson as json -from cuddlefish.util import filter_filenames, filter_dirnames - -class HarnessOptionAlreadyDefinedError(Exception): - """You cannot use --harness-option on keys that already exist in - harness-options.json""" - -ZIPSEP = "/" # always use "/" in zipfiles - -def make_zipfile_path(localroot, localpath): - return ZIPSEP.join(localpath[len(localroot)+1:].split(os.sep)) - -def mkzipdir(zf, path): - dirinfo = zipfile.ZipInfo(path) - dirinfo.external_attr = int("040755", 8) << 16L - zf.writestr(dirinfo, "") - -def build_xpi(template_root_dir, manifest, xpi_path, - harness_options, limit_to=None, extra_harness_options={}, - bundle_sdk=True, pkgdir=""): - IGNORED_FILES = [".hgignore", ".DS_Store", - "application.ini", xpi_path] - IGNORED_TOP_LVL_FILES = ["install.rdf"] - - files_to_copy = {} # maps zipfile path to local-disk abspath - dirs_to_create = set() # zipfile paths, no trailing slash - - zf = zipfile.ZipFile(xpi_path, "w", zipfile.ZIP_DEFLATED) - - zf.writestr('install.rdf', str(manifest)) - - # Handle add-on icon - if 'icon' in harness_options: - zf.write(os.path.join(str(harness_options['icon'])), 'icon.png') - del harness_options['icon'] - - if 'icon64' in harness_options: - zf.write(os.path.join(str(harness_options['icon64'])), 'icon64.png') - del harness_options['icon64'] - - # chrome.manifest - if os.path.isfile(os.path.join(pkgdir, 'chrome.manifest')): - files_to_copy['chrome.manifest'] = os.path.join(pkgdir, 'chrome.manifest') - - def add_special_dir(folder): - if os.path.exists(os.path.join(pkgdir, folder)): - dirs_to_create.add(folder) - # cp -r folder - abs_dirname = os.path.join(pkgdir, folder) - for dirpath, dirnames, filenames in os.walk(abs_dirname): - goodfiles = list(filter_filenames(filenames, IGNORED_FILES)) - dirnames[:] = filter_dirnames(dirnames) - for dirname in dirnames: - arcpath = make_zipfile_path(template_root_dir, - os.path.join(dirpath, dirname)) - dirs_to_create.add(arcpath) - for filename in goodfiles: - abspath = os.path.join(dirpath, filename) - arcpath = ZIPSEP.join( - [folder, - make_zipfile_path(abs_dirname, os.path.join(dirpath, filename)), - ]) - files_to_copy[str(arcpath)] = str(abspath) - - - # chrome folder (would contain content, skin, and locale folders typically) - add_special_dir('chrome') - # optionally include a `webextension/` dir from the add-on dir. - add_special_dir('webextension') - - for dirpath, dirnames, filenames in os.walk(template_root_dir): - if template_root_dir == dirpath: - filenames = list(filter_filenames(filenames, IGNORED_TOP_LVL_FILES)) - filenames = list(filter_filenames(filenames, IGNORED_FILES)) - dirnames[:] = filter_dirnames(dirnames) - for dirname in dirnames: - arcpath = make_zipfile_path(template_root_dir, - os.path.join(dirpath, dirname)) - dirs_to_create.add(arcpath) - for filename in filenames: - abspath = os.path.join(dirpath, filename) - arcpath = make_zipfile_path(template_root_dir, abspath) - files_to_copy[arcpath] = abspath - - # `packages` attribute contains a dictionnary of dictionnary - # of all packages sections directories - for packageName in harness_options['packages']: - base_arcpath = ZIPSEP.join(['resources', packageName]) - # Eventually strip sdk files. - if not bundle_sdk and packageName == 'addon-sdk': - continue - # Always write the top directory, even if it contains no files, since - # the harness will try to access it. - dirs_to_create.add(base_arcpath) - for sectionName in harness_options['packages'][packageName]: - abs_dirname = harness_options['packages'][packageName][sectionName] - base_arcpath = ZIPSEP.join(['resources', packageName, sectionName]) - # Always write the top directory, even if it contains no files, since - # the harness will try to access it. - dirs_to_create.add(base_arcpath) - # cp -r stuff from abs_dirname/ into ZIP/resources/RESOURCEBASE/ - for dirpath, dirnames, filenames in os.walk(abs_dirname): - goodfiles = list(filter_filenames(filenames, IGNORED_FILES)) - dirnames[:] = filter_dirnames(dirnames) - for filename in goodfiles: - abspath = os.path.join(dirpath, filename) - if limit_to is not None and abspath not in limit_to: - continue # strip unused files - arcpath = ZIPSEP.join( - ['resources', - packageName, - sectionName, - make_zipfile_path(abs_dirname, - os.path.join(dirpath, filename)), - ]) - files_to_copy[str(arcpath)] = str(abspath) - del harness_options['packages'] - - locales_json_data = {"locales": []} - mkzipdir(zf, "locale/") - for language in sorted(harness_options['locale']): - locales_json_data["locales"].append(language) - locale = harness_options['locale'][language] - # Be carefull about strings, we need to always ensure working with UTF-8 - jsonStr = json.dumps(locale, indent=1, sort_keys=True, ensure_ascii=False) - info = zipfile.ZipInfo('locale/' + language + '.json') - info.external_attr = 0644 << 16L - zf.writestr(info, jsonStr.encode( "utf-8" )) - del harness_options['locale'] - - jsonStr = json.dumps(locales_json_data, ensure_ascii=True) +"\n" - info = zipfile.ZipInfo('locales.json') - info.external_attr = 0644 << 16L - zf.writestr(info, jsonStr.encode("utf-8")) - - # now figure out which directories we need: all retained files parents - for arcpath in files_to_copy: - bits = arcpath.split("/") - for i in range(1,len(bits)): - parentpath = ZIPSEP.join(bits[0:i]) - dirs_to_create.add(parentpath) - - # Create zipfile in alphabetical order, with each directory before its - # files - for name in sorted(dirs_to_create.union(set(files_to_copy))): - if name in dirs_to_create: - mkzipdir(zf, name+"/") - if name in files_to_copy: - zf.write(files_to_copy[name], name) - - # Add extra harness options - harness_options = harness_options.copy() - for key,value in extra_harness_options.items(): - if key in harness_options: - msg = "Can't use --harness-option for existing key '%s'" % key - raise HarnessOptionAlreadyDefinedError(msg) - harness_options[key] = value - - # Write harness-options.json - zf.writestr('harness-options.json', json.dumps(harness_options, indent=1, - sort_keys=True)) - - zf.close() diff --git a/addon-sdk/source/python-lib/jetpack_sdk_env.py b/addon-sdk/source/python-lib/jetpack_sdk_env.py deleted file mode 100644 --- a/addon-sdk/source/python-lib/jetpack_sdk_env.py +++ /dev/null @@ -1,66 +0,0 @@ -# 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/. - -import sys -import os - -def welcome(): - """ - Perform a bunch of sanity tests to make sure the Add-on SDK - environment is sane, and then display a welcome message. - """ - - try: - if sys.version_info[0] > 2: - print ("Error: You appear to be using Python %d, but " - "the Add-on SDK only supports the Python 2.x line." % - (sys.version_info[0])) - return - - import mozrunner - - if 'CUDDLEFISH_ROOT' not in os.environ: - print ("Error: CUDDLEFISH_ROOT environment variable does " - "not exist! It should point to the root of the " - "Add-on SDK repository.") - return - - env_root = os.environ['CUDDLEFISH_ROOT'] - - bin_dir = os.path.join(env_root, 'bin') - python_lib_dir = os.path.join(env_root, 'python-lib') - path = os.environ['PATH'].split(os.path.pathsep) - - if bin_dir not in path: - print ("Warning: the Add-on SDK binary directory %s " - "does not appear to be in your PATH. You may " - "not be able to run 'cfx' or other SDK tools." % - bin_dir) - - if python_lib_dir not in sys.path: - print ("Warning: the Add-on SDK python-lib directory %s " - "does not appear to be in your sys.path, which " - "is odd because I'm running from it." % python_lib_dir) - - if not mozrunner.__path__[0].startswith(env_root): - print ("Warning: your mozrunner package is installed at %s, " - "which does not seem to be located inside the Jetpack " - "SDK. This may cause problems, and you may want to " - "uninstall the other version. See bug 556562 for " - "more information." % mozrunner.__path__[0]) - except Exception: - # Apparently we can't get the actual exception object in the - # 'except' clause in a way that's syntax-compatible for both - # Python 2.x and 3.x, so we'll have to use the traceback module. - - import traceback - _, e, _ = sys.exc_info() - print ("Verification of Add-on SDK environment failed (%s)." % e) - print ("Your SDK may not work properly.") - return - - print ("Welcome to the Add-on SDK. For the docs, visit https://developer.mozilla.org/en-US/Add-ons/SDK") - -if __name__ == '__main__': - welcome() diff --git a/addon-sdk/source/python-lib/mozrunner/__init__.py b/addon-sdk/source/python-lib/mozrunner/__init__.py deleted file mode 100644 --- a/addon-sdk/source/python-lib/mozrunner/__init__.py +++ /dev/null @@ -1,694 +0,0 @@ -# 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/. - -import os -import sys -import copy -import tempfile -import signal -import commands -import zipfile -import optparse -import killableprocess -import subprocess -import platform -import shutil -from StringIO import StringIO -from xml.dom import minidom - -from distutils import dir_util -from time import sleep - -# conditional (version-dependent) imports -try: - import simplejson -except ImportError: - import json as simplejson - -import logging -logger = logging.getLogger(__name__) - -# Use dir_util for copy/rm operations because shutil is all kinds of broken -copytree = dir_util.copy_tree -rmtree = dir_util.remove_tree - -def findInPath(fileName, path=os.environ['PATH']): - dirs = path.split(os.pathsep) - for dir in dirs: - if os.path.isfile(os.path.join(dir, fileName)): - return os.path.join(dir, fileName) - if os.name == 'nt' or sys.platform == 'cygwin': - if os.path.isfile(os.path.join(dir, fileName + ".exe")): - return os.path.join(dir, fileName + ".exe") - return None - -stdout = sys.stdout -stderr = sys.stderr -stdin = sys.stdin - -def run_command(cmd, env=None, **kwargs): - """Run the given command in killable process.""" - killable_kwargs = {'stdout':stdout ,'stderr':stderr, 'stdin':stdin} - killable_kwargs.update(kwargs) - - if sys.platform != "win32": - return killableprocess.Popen(cmd, preexec_fn=lambda : os.setpgid(0, 0), - env=env, **killable_kwargs) - else: - return killableprocess.Popen(cmd, env=env, **killable_kwargs) - -def getoutput(l): - tmp = tempfile.mktemp() - x = open(tmp, 'w') - subprocess.call(l, stdout=x, stderr=x) - x.close(); x = open(tmp, 'r') - r = x.read() ; x.close() - os.remove(tmp) - return r - -def get_pids(name, minimun_pid=0): - """Get all the pids matching name, exclude any pids below minimum_pid.""" - if os.name == 'nt' or sys.platform == 'cygwin': - import wpk - - pids = wpk.get_pids(name) - - else: - data = getoutput(['ps', 'ax']).splitlines() - pids = [int(line.split()[0]) for line in data if line.find(name) is not -1] - - matching_pids = [m for m in pids if m > minimun_pid] - return matching_pids - -def makedirs(name): - - head, tail = os.path.split(name) - if not tail: - head, tail = os.path.split(head) - if head and tail and not os.path.exists(head): - try: - makedirs(head) - except OSError, e: - pass - if tail == os.curdir: # xxx/newdir/. exists if xxx/newdir exists - return - try: - os.mkdir(name) - except: - pass - -# addon_details() copied from mozprofile -def addon_details(install_rdf_fh): - """ - returns a dictionary of details about the addon - - addon_path : path to the addon directory - Returns: - {'id': u'rainbow@colors.org', # id of the addon - 'version': u'1.4', # version of the addon - 'name': u'Rainbow', # name of the addon - 'unpack': # whether to unpack the addon - """ - - details = { - 'id': None, - 'unpack': False, - 'name': None, - 'version': None - } - - def get_namespace_id(doc, url): - attributes = doc.documentElement.attributes - namespace = "" - for i in range(attributes.length): - if attributes.item(i).value == url: - if ":" in attributes.item(i).name: - # If the namespace is not the default one remove 'xlmns:' - namespace = attributes.item(i).name.split(':')[1] + ":" - break - return namespace - - def get_text(element): - """Retrieve the text value of a given node""" - rc = [] - for node in element.childNodes: - if node.nodeType == node.TEXT_NODE: - rc.append(node.data) - return ''.join(rc).strip() - - doc = minidom.parse(install_rdf_fh) - - # Get the namespaces abbreviations - em = get_namespace_id(doc, "http://www.mozilla.org/2004/em-rdf#") - rdf = get_namespace_id(doc, "http://www.w3.org/1999/02/22-rdf-syntax-ns#") - - description = doc.getElementsByTagName(rdf + "Description").item(0) - for node in description.childNodes: - # Remove the namespace prefix from the tag for comparison - entry = node.nodeName.replace(em, "") - if entry in details.keys(): - details.update({ entry: get_text(node) }) - - # turn unpack into a true/false value - if isinstance(details['unpack'], basestring): - details['unpack'] = details['unpack'].lower() == 'true' - - return details - -class Profile(object): - """Handles all operations regarding profile. Created new profiles, installs extensions, - sets preferences and handles cleanup.""" - - def __init__(self, binary=None, profile=None, addons=None, - preferences=None): - - self.binary = binary - - self.create_new = not(bool(profile)) - if profile: - self.profile = profile - else: - self.profile = self.create_new_profile(self.binary) - - self.addons_installed = [] - self.addons = addons or [] - - ### set preferences from class preferences - preferences = preferences or {} - if hasattr(self.__class__, 'preferences'): - self.preferences = self.__class__.preferences.copy() - else: - self.preferences = {} - self.preferences.update(preferences) - - for addon in self.addons: - self.install_addon(addon) - - self.set_preferences(self.preferences) - - def create_new_profile(self, binary): - """Create a new clean profile in tmp which is a simple empty folder""" - profile = tempfile.mkdtemp(suffix='.mozrunner') - return profile - - def unpack_addon(self, xpi_zipfile, addon_path): - for name in xpi_zipfile.namelist(): - if name.endswith('/'): - makedirs(os.path.join(addon_path, name)) - else: - if not os.path.isdir(os.path.dirname(os.path.join(addon_path, name))): - makedirs(os.path.dirname(os.path.join(addon_path, name))) - data = xpi_zipfile.read(name) - f = open(os.path.join(addon_path, name), 'wb') - f.write(data) ; f.close() - zi = xpi_zipfile.getinfo(name) - os.chmod(os.path.join(addon_path,name), (zi.external_attr>>16)) - - def install_addon(self, path): - """Installs the given addon or directory of addons in the profile.""" - - extensions_path = os.path.join(self.profile, 'extensions') - if not os.path.exists(extensions_path): - os.makedirs(extensions_path) - - addons = [path] - if not path.endswith('.xpi') and not os.path.exists(os.path.join(path, 'install.rdf')): - addons = [os.path.join(path, x) for x in os.listdir(path)] - - for addon in addons: - if addon.endswith('.xpi'): - xpi_zipfile = zipfile.ZipFile(addon, "r") - details = addon_details(StringIO(xpi_zipfile.read('install.rdf'))) - addon_path = os.path.join(extensions_path, details["id"]) - if details.get("unpack", True): - self.unpack_addon(xpi_zipfile, addon_path) - self.addons_installed.append(addon_path) - else: - shutil.copy(addon, addon_path + '.xpi') - else: - # it's already unpacked, but we need to extract the id so we - # can copy it - details = addon_details(open(os.path.join(addon, "install.rdf"), "rb")) - addon_path = os.path.join(extensions_path, details["id"]) - shutil.copytree(addon, addon_path, symlinks=True) - - def set_preferences(self, preferences): - """Adds preferences dict to profile preferences""" - prefs_file = os.path.join(self.profile, 'user.js') - # Ensure that the file exists first otherwise create an empty file - if os.path.isfile(prefs_file): - f = open(prefs_file, 'a+') - else: - f = open(prefs_file, 'w') - - f.write('\n#MozRunner Prefs Start\n') - - pref_lines = ['user_pref(%s, %s);' % - (simplejson.dumps(k), simplejson.dumps(v) ) for k, v in - preferences.items()] - for line in pref_lines: - f.write(line+'\n') - f.write('#MozRunner Prefs End\n') - f.flush() ; f.close() - - def pop_preferences(self): - """ - pop the last set of preferences added - returns True if popped - """ - - # our magic markers - delimeters = ('#MozRunner Prefs Start', '#MozRunner Prefs End') - - lines = file(os.path.join(self.profile, 'user.js')).read().splitlines() - def last_index(_list, value): - """ - returns the last index of an item; - this should actually be part of python code but it isn't - """ - for index in reversed(range(len(_list))): - if _list[index] == value: - return index - s = last_index(lines, delimeters[0]) - e = last_index(lines, delimeters[1]) - - # ensure both markers are found - if s is None: - assert e is None, '%s found without %s' % (delimeters[1], delimeters[0]) - return False # no preferences found - elif e is None: - assert e is None, '%s found without %s' % (delimeters[0], delimeters[1]) - - # ensure the markers are in the proper order - assert e > s, '%s found at %s, while %s found at %s' (delimeter[1], e, delimeter[0], s) - - # write the prefs - cleaned_prefs = '\n'.join(lines[:s] + lines[e+1:]) - f = file(os.path.join(self.profile, 'user.js'), 'w') - f.write(cleaned_prefs) - f.close() - return True - - def clean_preferences(self): - """Removed preferences added by mozrunner.""" - while True: - if not self.pop_preferences(): - break - - def clean_addons(self): - """Cleans up addons in the profile.""" - for addon in self.addons_installed: - if os.path.isdir(addon): - rmtree(addon) - - def cleanup(self): - """Cleanup operations on the profile.""" - def oncleanup_error(function, path, excinfo): - #TODO: How should we handle this? - print "Error Cleaning up: " + str(excinfo[1]) - if self.create_new: - shutil.rmtree(self.profile, False, oncleanup_error) - else: - self.clean_preferences() - self.clean_addons() - -class FirefoxProfile(Profile): - """Specialized Profile subclass for Firefox""" - preferences = {# Don't automatically update the application - 'app.update.enabled' : False, - # Don't restore the last open set of tabs if the browser has crashed - 'browser.sessionstore.resume_from_crash': False, - # Don't check for the default web browser - 'browser.shell.checkDefaultBrowser' : False, - # Don't warn on exit when multiple tabs are open - 'browser.tabs.warnOnClose' : False, - # Don't warn when exiting the browser - 'browser.warnOnQuit': False, - # Only install add-ons from the profile and the app folder - 'extensions.enabledScopes' : 5, - # Don't automatically update add-ons - 'extensions.update.enabled' : False, - # Don't open a dialog to show available add-on updates - 'extensions.update.notifyUser' : False, - } - - # The possible names of application bundles on Mac OS X, in order of - # preference from most to least preferred. - # Note: Nightly is obsolete, as it has been renamed to FirefoxNightly, - # but it will still be present if users update an older nightly build - # via the app update service. - bundle_names = ['Firefox', 'FirefoxNightly', 'Nightly'] - - # The possible names of binaries, in order of preference from most to least - # preferred. - @property - def names(self): - if sys.platform == 'darwin': - return ['firefox', 'nightly', 'shiretoko'] - if (sys.platform == 'linux2') or (sys.platform in ('sunos5', 'solaris')): - return ['firefox', 'mozilla-firefox', 'iceweasel'] - if os.name == 'nt' or sys.platform == 'cygwin': - return ['firefox'] - -class ThunderbirdProfile(Profile): - preferences = {'extensions.update.enabled' : False, - 'extensions.update.notifyUser' : False, - 'browser.shell.checkDefaultBrowser' : False, - 'browser.tabs.warnOnClose' : False, - 'browser.warnOnQuit': False, - 'browser.sessionstore.resume_from_crash': False, - } - - # The possible names of application bundles on Mac OS X, in order of - # preference from most to least preferred. - bundle_names = ["Thunderbird", "Shredder"] - - # The possible names of binaries, in order of preference from most to least - # preferred. - names = ["thunderbird", "shredder"] - - -class Runner(object): - """Handles all running operations. Finds bins, runs and kills the process.""" - - def __init__(self, binary=None, profile=None, cmdargs=[], env=None, - kp_kwargs={}): - if binary is None: - self.binary = self.find_binary() - elif sys.platform == 'darwin' and binary.find('Contents/MacOS/') == -1: - self.binary = os.path.join(binary, 'Contents/MacOS/%s-bin' % self.names[0]) - else: - self.binary = binary - - if not os.path.exists(self.binary): - raise Exception("Binary path does not exist "+self.binary) - - if sys.platform == 'linux2' and self.binary.endswith('-bin'): - dirname = os.path.dirname(self.binary) - if os.environ.get('LD_LIBRARY_PATH', None): - os.environ['LD_LIBRARY_PATH'] = '%s:%s' % (os.environ['LD_LIBRARY_PATH'], dirname) - else: - os.environ['LD_LIBRARY_PATH'] = dirname - - # Disable the crash reporter by default - os.environ['MOZ_CRASHREPORTER_NO_REPORT'] = '1' - - self.profile = profile - - self.cmdargs = cmdargs - if env is None: - self.env = copy.copy(os.environ) - self.env.update({'MOZ_NO_REMOTE':"1",}) - else: - self.env = env - self.kp_kwargs = kp_kwargs or {} - - def find_binary(self): - """Finds the binary for self.names if one was not provided.""" - binary = None - if sys.platform in ('linux2', 'sunos5', 'solaris') \ - or sys.platform.startswith('freebsd'): - for name in reversed(self.names): - binary = findInPath(name) - elif os.name == 'nt' or sys.platform == 'cygwin': - - # find the default executable from the windows registry - try: - import _winreg - except ImportError: - pass - else: - sam_flags = [0] - # KEY_WOW64_32KEY etc only appeared in 2.6+, but that's OK as - # only 2.6+ has functioning 64bit builds. - if hasattr(_winreg, "KEY_WOW64_32KEY"): - if "64 bit" in sys.version: - # a 64bit Python should also look in the 32bit registry - sam_flags.append(_winreg.KEY_WOW64_32KEY) - else: - # possibly a 32bit Python on 64bit Windows, so look in - # the 64bit registry incase there is a 64bit app. - sam_flags.append(_winreg.KEY_WOW64_64KEY) - for sam_flag in sam_flags: - try: - # assumes self.app_name is defined, as it should be for - # implementors - keyname = r"Software\Mozilla\Mozilla %s" % self.app_name - sam = _winreg.KEY_READ | sam_flag - app_key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, keyname, 0, sam) - version, _type = _winreg.QueryValueEx(app_key, "CurrentVersion") - version_key = _winreg.OpenKey(app_key, version + r"\Main") - path, _ = _winreg.QueryValueEx(version_key, "PathToExe") - return path - except _winreg.error: - pass - - # search for the binary in the path - for name in reversed(self.names): - binary = findInPath(name) - if sys.platform == 'cygwin': - program_files = os.environ['PROGRAMFILES'] - else: - program_files = os.environ['ProgramFiles'] - - if binary is None: - for bin in [(program_files, 'Mozilla Firefox', 'firefox.exe'), - (os.environ.get("ProgramFiles(x86)"),'Mozilla Firefox', 'firefox.exe'), - (program_files, 'Nightly', 'firefox.exe'), - (os.environ.get("ProgramFiles(x86)"),'Nightly', 'firefox.exe'), - (program_files, 'Aurora', 'firefox.exe'), - (os.environ.get("ProgramFiles(x86)"),'Aurora', 'firefox.exe') - ]: - path = os.path.join(*bin) - if os.path.isfile(path): - binary = path - break - elif sys.platform == 'darwin': - for bundle_name in self.bundle_names: - # Look for the application bundle in the user's home directory - # or the system-wide /Applications directory. If we don't find - # it in one of those locations, we move on to the next possible - # bundle name. - appdir = os.path.join("~/Applications/%s.app" % bundle_name) - if not os.path.isdir(appdir): - appdir = "/Applications/%s.app" % bundle_name - if not os.path.isdir(appdir): - continue - - # Look for a binary with any of the possible binary names - # inside the application bundle. - for binname in self.names: - binpath = os.path.join(appdir, - "Contents/MacOS/%s-bin" % binname) - if (os.path.isfile(binpath)): - binary = binpath - break - - if binary: - break - - if binary is None: - raise Exception('Mozrunner could not locate your binary, you will need to set it.') - return binary - - @property - def command(self): - """Returns the command list to run.""" - cmd = [self.binary, '-profile', self.profile.profile] - # On i386 OS X machines, i386+x86_64 universal binaries need to be told - # to run as i386 binaries. If we're not running a i386+x86_64 universal - # binary, then this command modification is harmless. - if sys.platform == 'darwin': - if hasattr(platform, 'architecture') and platform.architecture()[0] == '32bit': - cmd = ['arch', '-i386'] + cmd - return cmd - - def get_repositoryInfo(self): - """Read repository information from application.ini and platform.ini.""" - import ConfigParser - - config = ConfigParser.RawConfigParser() - dirname = os.path.dirname(self.binary) - repository = { } - - for entry in [['application', 'App'], ['platform', 'Build']]: - (file, section) = entry - config.read(os.path.join(dirname, '%s.ini' % file)) - - for entry in [['SourceRepository', 'repository'], ['SourceStamp', 'changeset']]: - (key, id) = entry - - try: - repository['%s_%s' % (file, id)] = config.get(section, key); - except: - repository['%s_%s' % (file, id)] = None - - return repository - - def start(self): - """Run self.command in the proper environment.""" - if self.profile is None: - self.profile = self.profile_class() - self.process_handler = run_command(self.command+self.cmdargs, self.env, **self.kp_kwargs) - - def wait(self, timeout=None): - """Wait for the browser to exit.""" - self.process_handler.wait(timeout=timeout) - - if sys.platform != 'win32': - for name in self.names: - for pid in get_pids(name, self.process_handler.pid): - self.process_handler.pid = pid - self.process_handler.wait(timeout=timeout) - - def kill(self, kill_signal=signal.SIGTERM): - """Kill the browser""" - if sys.platform != 'win32': - self.process_handler.kill() - for name in self.names: - for pid in get_pids(name, self.process_handler.pid): - self.process_handler.pid = pid - self.process_handler.kill() - else: - try: - self.process_handler.kill(group=True) - # On windows, it sometimes behooves one to wait for dust to settle - # after killing processes. Let's try that. - # TODO: Bug 640047 is invesitgating the correct way to handle this case - self.process_handler.wait(timeout=10) - except Exception, e: - logger.error('Cannot kill process, '+type(e).__name__+' '+e.message) - - def stop(self): - self.kill() - -class FirefoxRunner(Runner): - """Specialized Runner subclass for running Firefox.""" - - app_name = 'Firefox' - profile_class = FirefoxProfile - - # The possible names of application bundles on Mac OS X, in order of - # preference from most to least preferred. - # Note: Nightly is obsolete, as it has been renamed to FirefoxNightly, - # but it will still be present if users update an older nightly build - # only via the app update service. - bundle_names = ['Firefox', 'FirefoxNightly', 'Nightly'] - - @property - def names(self): - if sys.platform == 'darwin': - return ['firefox', 'nightly', 'shiretoko'] - if sys.platform in ('linux2', 'sunos5', 'solaris') \ - or sys.platform.startswith('freebsd'): - return ['firefox', 'mozilla-firefox', 'iceweasel'] - if os.name == 'nt' or sys.platform == 'cygwin': - return ['firefox'] - -class ThunderbirdRunner(Runner): - """Specialized Runner subclass for running Thunderbird""" - - app_name = 'Thunderbird' - profile_class = ThunderbirdProfile - - # The possible names of application bundles on Mac OS X, in order of - # preference from most to least preferred. - bundle_names = ["Thunderbird", "Shredder"] - - # The possible names of binaries, in order of preference from most to least - # preferred. - names = ["thunderbird", "shredder"] - -class CLI(object): - """Command line interface.""" - - runner_class = FirefoxRunner - profile_class = FirefoxProfile - module = "mozrunner" - - parser_options = {("-b", "--binary",): dict(dest="binary", help="Binary path.", - metavar=None, default=None), - ('-p', "--profile",): dict(dest="profile", help="Profile path.", - metavar=None, default=None), - ('-a', "--addons",): dict(dest="addons", - help="Addons paths to install.", - metavar=None, default=None), - ("--info",): dict(dest="info", default=False, - action="store_true", - help="Print module information") - } - - def __init__(self): - """ Setup command line parser and parse arguments """ - self.metadata = self.get_metadata_from_egg() - self.parser = optparse.OptionParser(version="%prog " + self.metadata["Version"]) - for names, opts in self.parser_options.items(): - self.parser.add_option(*names, **opts) - (self.options, self.args) = self.parser.parse_args() - - if self.options.info: - self.print_metadata() - sys.exit(0) - - # XXX should use action='append' instead of rolling our own - try: - self.addons = self.options.addons.split(',') - except: - self.addons = [] - - def get_metadata_from_egg(self): - import pkg_resources - ret = {} - dist = pkg_resources.get_distribution(self.module) - if dist.has_metadata("PKG-INFO"): - for line in dist.get_metadata_lines("PKG-INFO"): - key, value = line.split(':', 1) - ret[key] = value - if dist.has_metadata("requires.txt"): - ret["Dependencies"] = "\n" + dist.get_metadata("requires.txt") - return ret - - def print_metadata(self, data=("Name", "Version", "Summary", "Home-page", - "Author", "Author-email", "License", "Platform", "Dependencies")): - for key in data: - if key in self.metadata: - print key + ": " + self.metadata[key] - - def create_runner(self): - """ Get the runner object """ - runner = self.get_runner(binary=self.options.binary) - profile = self.get_profile(binary=runner.binary, - profile=self.options.profile, - addons=self.addons) - runner.profile = profile - return runner - - def get_runner(self, binary=None, profile=None): - """Returns the runner instance for the given command line binary argument - the profile instance returned from self.get_profile().""" - return self.runner_class(binary, profile) - - def get_profile(self, binary=None, profile=None, addons=None, preferences=None): - """Returns the profile instance for the given command line arguments.""" - addons = addons or [] - preferences = preferences or {} - return self.profile_class(binary, profile, addons, preferences) - - def run(self): - runner = self.create_runner() - self.start(runner) - runner.profile.cleanup() - - def start(self, runner): - """Starts the runner and waits for Firefox to exitor Keyboard Interrupt. - Shoule be overwritten to provide custom running of the runner instance.""" - runner.start() - print 'Started:', ' '.join(runner.command) - try: - runner.wait() - except KeyboardInterrupt: - runner.stop() - - -def cli(): - CLI().run() diff --git a/addon-sdk/source/python-lib/mozrunner/killableprocess.py b/addon-sdk/source/python-lib/mozrunner/killableprocess.py deleted file mode 100644 --- a/addon-sdk/source/python-lib/mozrunner/killableprocess.py +++ /dev/null @@ -1,329 +0,0 @@ -# killableprocess - subprocesses which can be reliably killed -# -# Parts of this module are copied from the subprocess.py file contained -# in the Python distribution. -# -# Copyright (c) 2003-2004 by Peter Astrand -# -# Additions and modifications written by Benjamin Smedberg -# are Copyright (c) 2006 by the Mozilla Foundation -# -# -# More Modifications -# Copyright (c) 2006-2007 by Mike Taylor -# Copyright (c) 2007-2008 by Mikeal Rogers -# -# By obtaining, using, and/or copying this software and/or its -# associated documentation, you agree that you have read, understood, -# and will comply with the following terms and conditions: -# -# Permission to use, copy, modify, and distribute this software and -# its associated documentation for any purpose and without fee is -# hereby granted, provided that the above copyright notice appears in -# all copies, and that both that copyright notice and this permission -# notice appear in supporting documentation, and that the name of the -# author not be used in advertising or publicity pertaining to -# distribution of the software without specific, written prior -# permission. -# -# THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. -# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR -# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS -# OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, -# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION -# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -"""killableprocess - Subprocesses which can be reliably killed - -This module is a subclass of the builtin "subprocess" module. It allows -processes that launch subprocesses to be reliably killed on Windows (via the Popen.kill() method. - -It also adds a timeout argument to Wait() for a limited period of time before -forcefully killing the process. - -Note: On Windows, this module requires Windows 2000 or higher (no support for -Windows 95, 98, or NT 4.0). It also requires ctypes, which is bundled with -Python 2.5+ or available from http://python.net/crew/theller/ctypes/ -""" - -import subprocess -import sys -import os -import time -import datetime -import types -import exceptions - -try: - from subprocess import CalledProcessError -except ImportError: - # Python 2.4 doesn't implement CalledProcessError - class CalledProcessError(Exception): - """This exception is raised when a process run by check_call() returns - a non-zero exit status. The exit status will be stored in the - returncode attribute.""" - def __init__(self, returncode, cmd): - self.returncode = returncode - self.cmd = cmd - def __str__(self): - return "Command '%s' returned non-zero exit status %d" % (self.cmd, self.returncode) - -mswindows = (sys.platform == "win32") - -if mswindows: - import winprocess -else: - import signal - -# This is normally defined in win32con, but we don't want -# to incur the huge tree of dependencies (pywin32 and friends) -# just to get one constant. So here's our hack -STILL_ACTIVE = 259 - -def call(*args, **kwargs): - waitargs = {} - if "timeout" in kwargs: - waitargs["timeout"] = kwargs.pop("timeout") - - return Popen(*args, **kwargs).wait(**waitargs) - -def check_call(*args, **kwargs): - """Call a program with an optional timeout. If the program has a non-zero - exit status, raises a CalledProcessError.""" - - retcode = call(*args, **kwargs) - if retcode: - cmd = kwargs.get("args") - if cmd is None: - cmd = args[0] - raise CalledProcessError(retcode, cmd) - -if not mswindows: - def DoNothing(*args): - pass - -class Popen(subprocess.Popen): - kill_called = False - if mswindows: - def _execute_child(self, *args_tuple): - # workaround for bug 958609 - if sys.hexversion < 0x02070600: # prior to 2.7.6 - (args, executable, preexec_fn, close_fds, - cwd, env, universal_newlines, startupinfo, - creationflags, shell, - p2cread, p2cwrite, - c2pread, c2pwrite, - errread, errwrite) = args_tuple - to_close = set() - else: # 2.7.6 and later - (args, executable, preexec_fn, close_fds, - cwd, env, universal_newlines, startupinfo, - creationflags, shell, to_close, - p2cread, p2cwrite, - c2pread, c2pwrite, - errread, errwrite) = args_tuple - - if not isinstance(args, types.StringTypes): - args = subprocess.list2cmdline(args) - - # Always or in the create new process group - creationflags |= winprocess.CREATE_NEW_PROCESS_GROUP - - if startupinfo is None: - startupinfo = winprocess.STARTUPINFO() - - if None not in (p2cread, c2pwrite, errwrite): - startupinfo.dwFlags |= winprocess.STARTF_USESTDHANDLES - - startupinfo.hStdInput = int(p2cread) - startupinfo.hStdOutput = int(c2pwrite) - startupinfo.hStdError = int(errwrite) - if shell: - startupinfo.dwFlags |= winprocess.STARTF_USESHOWWINDOW - startupinfo.wShowWindow = winprocess.SW_HIDE - comspec = os.environ.get("COMSPEC", "cmd.exe") - args = comspec + " /c " + args - - # determine if we can create create a job - canCreateJob = winprocess.CanCreateJobObject() - - # set process creation flags - creationflags |= winprocess.CREATE_SUSPENDED - creationflags |= winprocess.CREATE_UNICODE_ENVIRONMENT - if canCreateJob: - # Uncomment this line below to discover very useful things about your environment - #print "++++ killableprocess: releng twistd patch not applied, we can create job objects" - creationflags |= winprocess.CREATE_BREAKAWAY_FROM_JOB - - # create the process - hp, ht, pid, tid = winprocess.CreateProcess( - executable, args, - None, None, # No special security - 1, # Must inherit handles! - creationflags, - winprocess.EnvironmentBlock(env), - cwd, startupinfo) - self._child_created = True - self._handle = hp - self._thread = ht - self.pid = pid - self.tid = tid - - if canCreateJob: - # We create a new job for this process, so that we can kill - # the process and any sub-processes - self._job = winprocess.CreateJobObject() - winprocess.AssignProcessToJobObject(self._job, int(hp)) - else: - self._job = None - - winprocess.ResumeThread(int(ht)) - ht.Close() - - if p2cread is not None: - p2cread.Close() - if c2pwrite is not None: - c2pwrite.Close() - if errwrite is not None: - errwrite.Close() - time.sleep(.1) - - def kill(self, group=True): - """Kill the process. If group=True, all sub-processes will also be killed.""" - self.kill_called = True - - if mswindows: - if group and self._job: - winprocess.TerminateJobObject(self._job, 127) - else: - winprocess.TerminateProcess(self._handle, 127) - self.returncode = 127 - else: - if group: - try: - os.killpg(self.pid, signal.SIGKILL) - except: pass - else: - os.kill(self.pid, signal.SIGKILL) - self.returncode = -9 - - def wait(self, timeout=None, group=True): - """Wait for the process to terminate. Returns returncode attribute. - If timeout seconds are reached and the process has not terminated, - it will be forcefully killed. If timeout is -1, wait will not - time out.""" - if timeout is not None: - # timeout is now in milliseconds - timeout = timeout * 1000 - - starttime = datetime.datetime.now() - - if mswindows: - if timeout is None: - timeout = -1 - rc = winprocess.WaitForSingleObject(self._handle, timeout) - - if (rc == winprocess.WAIT_OBJECT_0 or - rc == winprocess.WAIT_ABANDONED or - rc == winprocess.WAIT_FAILED): - # Object has either signaled, or the API call has failed. In - # both cases we want to give the OS the benefit of the doubt - # and supply a little time before we start shooting processes - # with an M-16. - - # Returns 1 if running, 0 if not, -1 if timed out - def check(): - now = datetime.datetime.now() - diff = now - starttime - if (diff.seconds * 1000000 + diff.microseconds) < (timeout * 1000): # (1000*1000) - if self._job: - if (winprocess.QueryInformationJobObject(self._job, 8)['BasicInfo']['ActiveProcesses'] > 0): - # Job Object is still containing active processes - return 1 - else: - # No job, we use GetExitCodeProcess, which will tell us if the process is still active - self.returncode = winprocess.GetExitCodeProcess(self._handle) - if (self.returncode == STILL_ACTIVE): - # Process still active, continue waiting - return 1 - # Process not active, return 0 - return 0 - else: - # Timed out, return -1 - return -1 - - notdone = check() - while notdone == 1: - time.sleep(.5) - notdone = check() - - if notdone == -1: - # Then check timed out, we have a hung process, attempt - # last ditch kill with explosives - self.kill(group) - - else: - # In this case waitforsingleobject timed out. We have to - # take the process behind the woodshed and shoot it. - self.kill(group) - - else: - if sys.platform in ('linux2', 'sunos5', 'solaris') \ - or sys.platform.startswith('freebsd'): - def group_wait(timeout): - try: - os.waitpid(self.pid, 0) - except OSError, e: - pass # If wait has already been called on this pid, bad things happen - return self.returncode - elif sys.platform == 'darwin': - def group_wait(timeout): - try: - count = 0 - if timeout is None and self.kill_called: - timeout = 10 # Have to set some kind of timeout or else this could go on forever - if timeout is None: - while 1: - os.killpg(self.pid, signal.SIG_DFL) - while ((count * 2) <= timeout): - os.killpg(self.pid, signal.SIG_DFL) - # count is increased by 500ms for every 0.5s of sleep - time.sleep(.5); count += 500 - except exceptions.OSError: - return self.returncode - - if timeout is None: - if group is True: - return group_wait(timeout) - else: - subprocess.Popen.wait(self) - return self.returncode - - returncode = False - - now = datetime.datetime.now() - diff = now - starttime - while (diff.seconds * 1000 * 1000 + diff.microseconds) < (timeout * 1000) and ( returncode is False ): - if group is True: - return group_wait(timeout) - else: - if subprocess.poll() is not None: - returncode = self.returncode - time.sleep(.5) - now = datetime.datetime.now() - diff = now - starttime - return self.returncode - - return self.returncode - # We get random maxint errors from subprocesses __del__ - __del__ = lambda self: None - -def setpgid_preexec_fn(): - os.setpgid(0, 0) - -def runCommand(cmd, **kwargs): - if sys.platform != "win32": - return Popen(cmd, preexec_fn=setpgid_preexec_fn, **kwargs) - else: - return Popen(cmd, **kwargs) diff --git a/addon-sdk/source/python-lib/mozrunner/qijo.py b/addon-sdk/source/python-lib/mozrunner/qijo.py deleted file mode 100644 --- a/addon-sdk/source/python-lib/mozrunner/qijo.py +++ /dev/null @@ -1,166 +0,0 @@ -# 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/. - -from ctypes import c_void_p, POINTER, sizeof, Structure, windll, WinError, WINFUNCTYPE, addressof, c_size_t, c_ulong -from ctypes.wintypes import BOOL, BYTE, DWORD, HANDLE, LARGE_INTEGER - -LPVOID = c_void_p -LPDWORD = POINTER(DWORD) -SIZE_T = c_size_t -ULONG_PTR = POINTER(c_ulong) - -# A ULONGLONG is a 64-bit unsigned integer. -# Thus there are 8 bytes in a ULONGLONG. -# XXX why not import c_ulonglong ? -ULONGLONG = BYTE * 8 - -class IO_COUNTERS(Structure): - # The IO_COUNTERS struct is 6 ULONGLONGs. - # TODO: Replace with non-dummy fields. - _fields_ = [('dummy', ULONGLONG * 6)] - -class JOBOBJECT_BASIC_ACCOUNTING_INFORMATION(Structure): - _fields_ = [('TotalUserTime', LARGE_INTEGER), - ('TotalKernelTime', LARGE_INTEGER), - ('ThisPeriodTotalUserTime', LARGE_INTEGER), - ('ThisPeriodTotalKernelTime', LARGE_INTEGER), - ('TotalPageFaultCount', DWORD), - ('TotalProcesses', DWORD), - ('ActiveProcesses', DWORD), - ('TotalTerminatedProcesses', DWORD)] - -class JOBOBJECT_BASIC_AND_IO_ACCOUNTING_INFORMATION(Structure): - _fields_ = [('BasicInfo', JOBOBJECT_BASIC_ACCOUNTING_INFORMATION), - ('IoInfo', IO_COUNTERS)] - -# see http://msdn.microsoft.com/en-us/library/ms684147%28VS.85%29.aspx -class JOBOBJECT_BASIC_LIMIT_INFORMATION(Structure): - _fields_ = [('PerProcessUserTimeLimit', LARGE_INTEGER), - ('PerJobUserTimeLimit', LARGE_INTEGER), - ('LimitFlags', DWORD), - ('MinimumWorkingSetSize', SIZE_T), - ('MaximumWorkingSetSize', SIZE_T), - ('ActiveProcessLimit', DWORD), - ('Affinity', ULONG_PTR), - ('PriorityClass', DWORD), - ('SchedulingClass', DWORD) - ] - -# see http://msdn.microsoft.com/en-us/library/ms684156%28VS.85%29.aspx -class JOBOBJECT_EXTENDED_LIMIT_INFORMATION(Structure): - _fields_ = [('BasicLimitInformation', JOBOBJECT_BASIC_LIMIT_INFORMATION), - ('IoInfo', IO_COUNTERS), - ('ProcessMemoryLimit', SIZE_T), - ('JobMemoryLimit', SIZE_T), - ('PeakProcessMemoryUsed', SIZE_T), - ('PeakJobMemoryUsed', SIZE_T)] - -# XXX Magical numbers like 8 should be documented -JobObjectBasicAndIoAccountingInformation = 8 - -# ...like magical number 9 comes from -# http://community.flexerasoftware.com/archive/index.php?t-181670.html -# I wish I had a more canonical source -JobObjectExtendedLimitInformation = 9 - -class JobObjectInfo(object): - mapping = { 'JobObjectBasicAndIoAccountingInformation': 8, - 'JobObjectExtendedLimitInformation': 9 - } - structures = { 8: JOBOBJECT_BASIC_AND_IO_ACCOUNTING_INFORMATION, - 9: JOBOBJECT_EXTENDED_LIMIT_INFORMATION - } - def __init__(self, _class): - if isinstance(_class, basestring): - assert _class in self.mapping, 'Class should be one of %s; you gave %s' % (self.mapping, _class) - _class = self.mapping[_class] - assert _class in self.structures, 'Class should be one of %s; you gave %s' % (self.structures, _class) - self.code = _class - self.info = self.structures[_class]() - - -QueryInformationJobObjectProto = WINFUNCTYPE( - BOOL, # Return type - HANDLE, # hJob - DWORD, # JobObjectInfoClass - LPVOID, # lpJobObjectInfo - DWORD, # cbJobObjectInfoLength - LPDWORD # lpReturnLength - ) - -QueryInformationJobObjectFlags = ( - (1, 'hJob'), - (1, 'JobObjectInfoClass'), - (1, 'lpJobObjectInfo'), - (1, 'cbJobObjectInfoLength'), - (1, 'lpReturnLength', None) - ) - -_QueryInformationJobObject = QueryInformationJobObjectProto( - ('QueryInformationJobObject', windll.kernel32), - QueryInformationJobObjectFlags - ) - -class SubscriptableReadOnlyStruct(object): - def __init__(self, struct): - self._struct = struct - - def _delegate(self, name): - result = getattr(self._struct, name) - if isinstance(result, Structure): - return SubscriptableReadOnlyStruct(result) - return result - - def __getitem__(self, name): - match = [fname for fname, ftype in self._struct._fields_ - if fname == name] - if match: - return self._delegate(name) - raise KeyError(name) - - def __getattr__(self, name): - return self._delegate(name) - -def QueryInformationJobObject(hJob, JobObjectInfoClass): - jobinfo = JobObjectInfo(JobObjectInfoClass) - result = _QueryInformationJobObject( - hJob=hJob, - JobObjectInfoClass=jobinfo.code, - lpJobObjectInfo=addressof(jobinfo.info), - cbJobObjectInfoLength=sizeof(jobinfo.info) - ) - if not result: - raise WinError() - return SubscriptableReadOnlyStruct(jobinfo.info) - -def test_qijo(): - from killableprocess import Popen - - popen = Popen('c:\\windows\\notepad.exe') - - try: - result = QueryInformationJobObject(0, 8) - raise AssertionError('throw should occur') - except WindowsError, e: - pass - - try: - result = QueryInformationJobObject(0, 1) - raise AssertionError('throw should occur') - except NotImplementedError, e: - pass - - result = QueryInformationJobObject(popen._job, 8) - if result['BasicInfo']['ActiveProcesses'] != 1: - raise AssertionError('expected ActiveProcesses to be 1') - popen.kill() - - result = QueryInformationJobObject(popen._job, 8) - if result.BasicInfo.ActiveProcesses != 0: - raise AssertionError('expected ActiveProcesses to be 0') - -if __name__ == '__main__': - print "testing." - test_qijo() - print "success!" diff --git a/addon-sdk/source/python-lib/mozrunner/winprocess.py b/addon-sdk/source/python-lib/mozrunner/winprocess.py deleted file mode 100644 --- a/addon-sdk/source/python-lib/mozrunner/winprocess.py +++ /dev/null @@ -1,379 +0,0 @@ -# A module to expose various thread/process/job related structures and -# methods from kernel32 -# -# The MIT License -# -# Copyright (c) 2003-2004 by Peter Astrand -# -# Additions and modifications written by Benjamin Smedberg -# are Copyright (c) 2006 by the Mozilla Foundation -# -# -# More Modifications -# Copyright (c) 2006-2007 by Mike Taylor -# Copyright (c) 2007-2008 by Mikeal Rogers -# -# By obtaining, using, and/or copying this software and/or its -# associated documentation, you agree that you have read, understood, -# and will comply with the following terms and conditions: -# -# Permission to use, copy, modify, and distribute this software and -# its associated documentation for any purpose and without fee is -# hereby granted, provided that the above copyright notice appears in -# all copies, and that both that copyright notice and this permission -# notice appear in supporting documentation, and that the name of the -# author not be used in advertising or publicity pertaining to -# distribution of the software without specific, written prior -# permission. -# -# THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. -# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR -# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS -# OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, -# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION -# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -from ctypes import c_void_p, POINTER, sizeof, Structure, windll, WinError, WINFUNCTYPE -from ctypes.wintypes import BOOL, BYTE, DWORD, HANDLE, LPCWSTR, LPWSTR, UINT, WORD, \ - c_buffer, c_ulong, byref -from qijo import QueryInformationJobObject - -LPVOID = c_void_p -LPBYTE = POINTER(BYTE) -LPDWORD = POINTER(DWORD) -LPBOOL = POINTER(BOOL) - -def ErrCheckBool(result, func, args): - """errcheck function for Windows functions that return a BOOL True - on success""" - if not result: - raise WinError() - return args - - -# AutoHANDLE - -class AutoHANDLE(HANDLE): - """Subclass of HANDLE which will call CloseHandle() on deletion.""" - - CloseHandleProto = WINFUNCTYPE(BOOL, HANDLE) - CloseHandle = CloseHandleProto(("CloseHandle", windll.kernel32)) - CloseHandle.errcheck = ErrCheckBool - - def Close(self): - if self.value and self.value != HANDLE(-1).value: - self.CloseHandle(self) - self.value = 0 - - def __del__(self): - self.Close() - - def __int__(self): - return self.value - -def ErrCheckHandle(result, func, args): - """errcheck function for Windows functions that return a HANDLE.""" - if not result: - raise WinError() - return AutoHANDLE(result) - -# PROCESS_INFORMATION structure - -class PROCESS_INFORMATION(Structure): - _fields_ = [("hProcess", HANDLE), - ("hThread", HANDLE), - ("dwProcessID", DWORD), - ("dwThreadID", DWORD)] - - def __init__(self): - Structure.__init__(self) - - self.cb = sizeof(self) - -LPPROCESS_INFORMATION = POINTER(PROCESS_INFORMATION) - -# STARTUPINFO structure - -class STARTUPINFO(Structure): - _fields_ = [("cb", DWORD), - ("lpReserved", LPWSTR), - ("lpDesktop", LPWSTR), - ("lpTitle", LPWSTR), - ("dwX", DWORD), - ("dwY", DWORD), - ("dwXSize", DWORD), - ("dwYSize", DWORD), - ("dwXCountChars", DWORD), - ("dwYCountChars", DWORD), - ("dwFillAttribute", DWORD), - ("dwFlags", DWORD), - ("wShowWindow", WORD), - ("cbReserved2", WORD), - ("lpReserved2", LPBYTE), - ("hStdInput", HANDLE), - ("hStdOutput", HANDLE), - ("hStdError", HANDLE) - ] -LPSTARTUPINFO = POINTER(STARTUPINFO) - -SW_HIDE = 0 - -STARTF_USESHOWWINDOW = 0x01 -STARTF_USESIZE = 0x02 -STARTF_USEPOSITION = 0x04 -STARTF_USECOUNTCHARS = 0x08 -STARTF_USEFILLATTRIBUTE = 0x10 -STARTF_RUNFULLSCREEN = 0x20 -STARTF_FORCEONFEEDBACK = 0x40 -STARTF_FORCEOFFFEEDBACK = 0x80 -STARTF_USESTDHANDLES = 0x100 - -# EnvironmentBlock - -class EnvironmentBlock: - """An object which can be passed as the lpEnv parameter of CreateProcess. - It is initialized with a dictionary.""" - - def __init__(self, dict): - if not dict: - self._as_parameter_ = None - else: - values = ["%s=%s" % (key, value) - for (key, value) in dict.iteritems()] - values.append("") - self._as_parameter_ = LPCWSTR("\0".join(values)) - -# CreateProcess() - -CreateProcessProto = WINFUNCTYPE(BOOL, # Return type - LPCWSTR, # lpApplicationName - LPWSTR, # lpCommandLine - LPVOID, # lpProcessAttributes - LPVOID, # lpThreadAttributes - BOOL, # bInheritHandles - DWORD, # dwCreationFlags - LPVOID, # lpEnvironment - LPCWSTR, # lpCurrentDirectory - LPSTARTUPINFO, # lpStartupInfo - LPPROCESS_INFORMATION # lpProcessInformation - ) - -CreateProcessFlags = ((1, "lpApplicationName", None), - (1, "lpCommandLine"), - (1, "lpProcessAttributes", None), - (1, "lpThreadAttributes", None), - (1, "bInheritHandles", True), - (1, "dwCreationFlags", 0), - (1, "lpEnvironment", None), - (1, "lpCurrentDirectory", None), - (1, "lpStartupInfo"), - (2, "lpProcessInformation")) - -def ErrCheckCreateProcess(result, func, args): - ErrCheckBool(result, func, args) - # return a tuple (hProcess, hThread, dwProcessID, dwThreadID) - pi = args[9] - return AutoHANDLE(pi.hProcess), AutoHANDLE(pi.hThread), pi.dwProcessID, pi.dwThreadID - -CreateProcess = CreateProcessProto(("CreateProcessW", windll.kernel32), - CreateProcessFlags) -CreateProcess.errcheck = ErrCheckCreateProcess - -# flags for CreateProcess -CREATE_BREAKAWAY_FROM_JOB = 0x01000000 -CREATE_DEFAULT_ERROR_MODE = 0x04000000 -CREATE_NEW_CONSOLE = 0x00000010 -CREATE_NEW_PROCESS_GROUP = 0x00000200 -CREATE_NO_WINDOW = 0x08000000 -CREATE_SUSPENDED = 0x00000004 -CREATE_UNICODE_ENVIRONMENT = 0x00000400 - -# flags for job limit information -# see http://msdn.microsoft.com/en-us/library/ms684147%28VS.85%29.aspx -JOB_OBJECT_LIMIT_BREAKAWAY_OK = 0x00000800 -JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK = 0x00001000 - -# XXX these flags should be documented -DEBUG_ONLY_THIS_PROCESS = 0x00000002 -DEBUG_PROCESS = 0x00000001 -DETACHED_PROCESS = 0x00000008 - -# CreateJobObject() - -CreateJobObjectProto = WINFUNCTYPE(HANDLE, # Return type - LPVOID, # lpJobAttributes - LPCWSTR # lpName - ) - -CreateJobObjectFlags = ((1, "lpJobAttributes", None), - (1, "lpName", None)) - -CreateJobObject = CreateJobObjectProto(("CreateJobObjectW", windll.kernel32), - CreateJobObjectFlags) -CreateJobObject.errcheck = ErrCheckHandle - -# AssignProcessToJobObject() - -AssignProcessToJobObjectProto = WINFUNCTYPE(BOOL, # Return type - HANDLE, # hJob - HANDLE # hProcess - ) -AssignProcessToJobObjectFlags = ((1, "hJob"), - (1, "hProcess")) -AssignProcessToJobObject = AssignProcessToJobObjectProto( - ("AssignProcessToJobObject", windll.kernel32), - AssignProcessToJobObjectFlags) -AssignProcessToJobObject.errcheck = ErrCheckBool - -# GetCurrentProcess() -# because os.getPid() is way too easy -GetCurrentProcessProto = WINFUNCTYPE(HANDLE # Return type - ) -GetCurrentProcessFlags = () -GetCurrentProcess = GetCurrentProcessProto( - ("GetCurrentProcess", windll.kernel32), - GetCurrentProcessFlags) -GetCurrentProcess.errcheck = ErrCheckHandle - -# IsProcessInJob() -try: - IsProcessInJobProto = WINFUNCTYPE(BOOL, # Return type - HANDLE, # Process Handle - HANDLE, # Job Handle - LPBOOL # Result - ) - IsProcessInJobFlags = ((1, "ProcessHandle"), - (1, "JobHandle", HANDLE(0)), - (2, "Result")) - IsProcessInJob = IsProcessInJobProto( - ("IsProcessInJob", windll.kernel32), - IsProcessInJobFlags) - IsProcessInJob.errcheck = ErrCheckBool -except AttributeError: - # windows 2k doesn't have this API - def IsProcessInJob(process): - return False - - -# ResumeThread() - -def ErrCheckResumeThread(result, func, args): - if result == -1: - raise WinError() - - return args - -ResumeThreadProto = WINFUNCTYPE(DWORD, # Return type - HANDLE # hThread - ) -ResumeThreadFlags = ((1, "hThread"),) -ResumeThread = ResumeThreadProto(("ResumeThread", windll.kernel32), - ResumeThreadFlags) -ResumeThread.errcheck = ErrCheckResumeThread - -# TerminateProcess() - -TerminateProcessProto = WINFUNCTYPE(BOOL, # Return type - HANDLE, # hProcess - UINT # uExitCode - ) -TerminateProcessFlags = ((1, "hProcess"), - (1, "uExitCode", 127)) -TerminateProcess = TerminateProcessProto( - ("TerminateProcess", windll.kernel32), - TerminateProcessFlags) -TerminateProcess.errcheck = ErrCheckBool - -# TerminateJobObject() - -TerminateJobObjectProto = WINFUNCTYPE(BOOL, # Return type - HANDLE, # hJob - UINT # uExitCode - ) -TerminateJobObjectFlags = ((1, "hJob"), - (1, "uExitCode", 127)) -TerminateJobObject = TerminateJobObjectProto( - ("TerminateJobObject", windll.kernel32), - TerminateJobObjectFlags) -TerminateJobObject.errcheck = ErrCheckBool - -# WaitForSingleObject() - -WaitForSingleObjectProto = WINFUNCTYPE(DWORD, # Return type - HANDLE, # hHandle - DWORD, # dwMilliseconds - ) -WaitForSingleObjectFlags = ((1, "hHandle"), - (1, "dwMilliseconds", -1)) -WaitForSingleObject = WaitForSingleObjectProto( - ("WaitForSingleObject", windll.kernel32), - WaitForSingleObjectFlags) - -INFINITE = -1 -WAIT_TIMEOUT = 0x0102 -WAIT_OBJECT_0 = 0x0 -WAIT_ABANDONED = 0x0080 -WAIT_FAILED = 0xFFFFFFFF - -# GetExitCodeProcess() - -GetExitCodeProcessProto = WINFUNCTYPE(BOOL, # Return type - HANDLE, # hProcess - LPDWORD, # lpExitCode - ) -GetExitCodeProcessFlags = ((1, "hProcess"), - (2, "lpExitCode")) -GetExitCodeProcess = GetExitCodeProcessProto( - ("GetExitCodeProcess", windll.kernel32), - GetExitCodeProcessFlags) -GetExitCodeProcess.errcheck = ErrCheckBool - -def CanCreateJobObject(): - # Running firefox in a job (from cfx) hangs on sites using flash plugin - # so job creation is turned off for now. (see Bug 768651). - return False - -### testing functions - -def parent(): - print 'Starting parent' - currentProc = GetCurrentProcess() - if IsProcessInJob(currentProc): - print >> sys.stderr, "You should not be in a job object to test" - sys.exit(1) - assert CanCreateJobObject() - print 'File: %s' % __file__ - command = [sys.executable, __file__, '-child'] - print 'Running command: %s' % command - process = Popen(command) - process.kill() - code = process.returncode - print 'Child code: %s' % code - assert code == 127 - -def child(): - print 'Starting child' - currentProc = GetCurrentProcess() - injob = IsProcessInJob(currentProc) - print "Is in a job?: %s" % injob - can_create = CanCreateJobObject() - print 'Can create job?: %s' % can_create - process = Popen('c:\\windows\\notepad.exe') - assert process._job - jobinfo = QueryInformationJobObject(process._job, 'JobObjectExtendedLimitInformation') - print 'Job info: %s' % jobinfo - limitflags = jobinfo['BasicLimitInformation']['LimitFlags'] - print 'LimitFlags: %s' % limitflags - process.kill() - -if __name__ == '__main__': - import sys - from killableprocess import Popen - nargs = len(sys.argv[1:]) - if nargs: - if nargs != 1 or sys.argv[1] != '-child': - raise AssertionError('Wrong flags; run like `python /path/to/winprocess.py`') - child() - else: - parent() diff --git a/addon-sdk/source/python-lib/mozrunner/wpk.py b/addon-sdk/source/python-lib/mozrunner/wpk.py deleted file mode 100644 --- a/addon-sdk/source/python-lib/mozrunner/wpk.py +++ /dev/null @@ -1,80 +0,0 @@ -# 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/. - -from ctypes import sizeof, windll, addressof, c_wchar, create_unicode_buffer -from ctypes.wintypes import DWORD, HANDLE - -PROCESS_TERMINATE = 0x0001 -PROCESS_QUERY_INFORMATION = 0x0400 -PROCESS_VM_READ = 0x0010 - -def get_pids(process_name): - BIG_ARRAY = DWORD * 4096 - processes = BIG_ARRAY() - needed = DWORD() - - pids = [] - result = windll.psapi.EnumProcesses(processes, - sizeof(processes), - addressof(needed)) - if not result: - return pids - - num_results = needed.value / sizeof(DWORD) - - for i in range(num_results): - pid = processes[i] - process = windll.kernel32.OpenProcess(PROCESS_QUERY_INFORMATION | - PROCESS_VM_READ, - 0, pid) - if process: - module = HANDLE() - result = windll.psapi.EnumProcessModules(process, - addressof(module), - sizeof(module), - addressof(needed)) - if result: - name = create_unicode_buffer(1024) - result = windll.psapi.GetModuleBaseNameW(process, module, - name, len(name)) - # TODO: This might not be the best way to - # match a process name; maybe use a regexp instead. - if name.value.startswith(process_name): - pids.append(pid) - windll.kernel32.CloseHandle(module) - windll.kernel32.CloseHandle(process) - - return pids - -def kill_pid(pid): - process = windll.kernel32.OpenProcess(PROCESS_TERMINATE, 0, pid) - if process: - windll.kernel32.TerminateProcess(process, 0) - windll.kernel32.CloseHandle(process) - -if __name__ == '__main__': - import subprocess - import time - - # This test just opens a new notepad instance and kills it. - - name = 'notepad' - - old_pids = set(get_pids(name)) - subprocess.Popen([name]) - time.sleep(0.25) - new_pids = set(get_pids(name)).difference(old_pids) - - if len(new_pids) != 1: - raise Exception('%s was not opened or get_pids() is ' - 'malfunctioning' % name) - - kill_pid(tuple(new_pids)[0]) - - newest_pids = set(get_pids(name)).difference(old_pids) - - if len(newest_pids) != 0: - raise Exception('kill_pid() is malfunctioning') - - print "Test passed." diff --git a/addon-sdk/source/python-lib/plural-rules-generator.py b/addon-sdk/source/python-lib/plural-rules-generator.py deleted file mode 100644 --- a/addon-sdk/source/python-lib/plural-rules-generator.py +++ /dev/null @@ -1,185 +0,0 @@ -# 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/. - -# Program used to generate /packages/api-utils/lib/l10n/plural-rules.js -# Fetch unicode.org data in order to build functions specific to each language -# that will return for a given integer, its plural form name. -# Plural form names are: zero, one, two, few, many, other. -# -# More information here: -# http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html -# http://cldr.unicode.org/index/cldr-spec/plural-rules - -# Usage: -# $ python plural-rules-generator.py > ../packages/api-utils/lib/l10n/plural-rules.js - -import urllib2 -import xml.dom.minidom -import json -import re - -PRINT_CONDITIONS_IN_COMMENTS = False - -UNICODE_ORG_XML_URL = "http://unicode.org/repos/cldr/trunk/common/supplemental/plurals.xml" - -CONDITION_RE = r'n( mod \d+)? (is|in|within|(not in))( not)? ([^\s]+)' - - -def parseCondition(g): - """ - For a given regexp.MatchObject `g` for `CONDITION_RE`, - returns the equivalent JS piece of code - i.e. maps pseudo conditional language from unicode.org XML to JS code - """ - lvalue = "n" - if g.group(1): - lvalue = "(n %% %d)" % int(g.group(1).replace("mod ", "")) - - operator = g.group(2) - if g.group(4): - operator += " not" - - rvalue = g.group(5) - - if operator == "is": - return "%s == %s" % (lvalue, rvalue) - if operator == "is not": - return "%s != %s" % (lvalue, rvalue) - - # "in", "within" or "not in" case: - notPrefix = "" - if operator == "not in": - notPrefix = "!" - - # `rvalue` is a comma seperated list of either: - # - numbers: 42 - # - ranges: 42..72 - sections = rvalue.split(',') - - if ".." not in rvalue: - # If we don't have range, but only a list of integer, - # we can simplify the generated code by using `isIn` - # n in 1,3,6,42 - return "%sisIn(%s, [%s])" % (notPrefix, lvalue, ", ".join(sections)) - - # n in 1..42 - # n in 1..3,42 - subCondition = [] - integers = [] - for sub in sections: - if ".." in sub: - left, right = sub.split("..") - subCondition.append("isBetween(%s, %d, %d)" % ( - lvalue, - int(left), - int(right) - )) - else: - integers.append(int(sub)) - if len(integers) > 1: - subCondition.append("isIn(%s, [%s])" % (lvalue, ", ".join(integers))) - elif len(integers) == 1: - subCondition.append("(%s == %s)" % (lvalue, integers[0])) - return "%s(%s)" % (notPrefix, " || ".join(subCondition)) - -def computeRules(): - """ - Fetch plural rules data directly from unicode.org website: - """ - url = UNICODE_ORG_XML_URL - f = urllib2.urlopen(url) - doc = xml.dom.minidom.parse(f) - - # Read XML document and extract locale to rules mapping - localesMapping = {} - algorithms = {} - for index,pluralRules in enumerate(doc.getElementsByTagName("pluralRules")): - if not index in algorithms: - algorithms[index] = {} - for locale in pluralRules.getAttribute("locales").split(): - localesMapping[locale] = index - for rule in pluralRules.childNodes: - if rule.nodeType != rule.ELEMENT_NODE or rule.tagName != "pluralRule": - continue - pluralForm = rule.getAttribute("count") - algorithm = rule.firstChild.nodeValue - algorithms[index][pluralForm] = algorithm - - # Go through all rules and compute a Javascript code for each of them - rules = {} - for index,rule in algorithms.iteritems(): - lines = [] - for pluralForm in rule: - condition = rule[pluralForm] - originalCondition = str(condition) - - # Convert pseudo language to JS code - condition = rule[pluralForm].lower() - condition = re.sub(CONDITION_RE, parseCondition, condition) - condition = re.sub(r'or', "||", condition) - condition = re.sub(r'and', "&&", condition) - - # Prints original condition in unicode.org pseudo language - if PRINT_CONDITIONS_IN_COMMENTS: - lines.append( '// %s' % originalCondition ) - - lines.append( 'if (%s)' % condition ) - lines.append( ' return "%s";' % pluralForm ) - - rules[index] = "\n ".join(lines) - return localesMapping, rules - - -localesMapping, rules = computeRules() - -rulesLines = [] -for index in rules: - lines = rules[index] - rulesLines.append('"%d": function (n) {' % index) - rulesLines.append(' %s' % lines) - rulesLines.append(' return "other"') - rulesLines.append('},') - -print """/* 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/. */ - -// This file is automatically generated with /python-lib/plural-rules-generator.py -// Fetching data from: %s - -// Mapping of short locale name == to == > rule index in following list -const LOCALES_TO_RULES = %s; - -// Utility functions for plural rules methods -function isIn(n, list) { - return list.indexOf(n) !== -1; -} -function isBetween(n, start, end) { - return start <= n && n <= end; -} - -// List of all plural rules methods, that maps an integer to the plural form name to use -const RULES = { - %s -}; - -/** - * Return a function that gives the plural form name for a given integer - * for the specified `locale` - * let fun = getRulesForLocale('en'); - * fun(1) -> 'one' - * fun(0) -> 'other' - * fun(1000) -> 'other' - */ -exports.getRulesForLocale = function getRulesForLocale(locale) { - let index = LOCALES_TO_RULES[locale]; - if (!(index in RULES)) { - console.warn('Plural form unknown for locale "' + locale + '"'); - return function () { return "other"; }; - } - return RULES[index]; -} -""" % (UNICODE_ORG_XML_URL, - json.dumps(localesMapping, sort_keys=True, indent=2), - "\n ".join(rulesLines)) diff --git a/addon-sdk/source/python-lib/simplejson/LICENSE.txt b/addon-sdk/source/python-lib/simplejson/LICENSE.txt deleted file mode 100644 --- a/addon-sdk/source/python-lib/simplejson/LICENSE.txt +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2006 Bob Ippolito - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/addon-sdk/source/python-lib/simplejson/__init__.py b/addon-sdk/source/python-lib/simplejson/__init__.py deleted file mode 100644 --- a/addon-sdk/source/python-lib/simplejson/__init__.py +++ /dev/null @@ -1,376 +0,0 @@ -r""" -A simple, fast, extensible JSON encoder and decoder - -JSON (JavaScript Object Notation) is a subset of -JavaScript syntax (ECMA-262 3rd edition) used as a lightweight data -interchange format. - -simplejson exposes an API familiar to uses of the standard library -marshal and pickle modules. - -Encoding basic Python object hierarchies:: - - >>> import simplejson - >>> simplejson.dumps(['foo', {'bar': ('baz', None, 1.0, 2)}]) - '["foo", {"bar": ["baz", null, 1.0, 2]}]' - >>> print simplejson.dumps("\"foo\bar") - "\"foo\bar" - >>> print simplejson.dumps(u'\u1234') - "\u1234" - >>> print simplejson.dumps('\\') - "\\" - >>> print simplejson.dumps({"c": 0, "b": 0, "a": 0}, sort_keys=True) - {"a": 0, "b": 0, "c": 0} - >>> from StringIO import StringIO - >>> io = StringIO() - >>> simplejson.dump(['streaming API'], io) - >>> io.getvalue() - '["streaming API"]' - -Compact encoding:: - - >>> import simplejson - >>> simplejson.dumps([1,2,3,{'4': 5, '6': 7}], separators=(',',':')) - '[1,2,3,{"4":5,"6":7}]' - -Pretty printing:: - - >>> import simplejson - >>> print simplejson.dumps({'4': 5, '6': 7}, sort_keys=True, indent=4) - { - "4": 5, - "6": 7 - } - -Decoding JSON:: - - >>> import simplejson - >>> simplejson.loads('["foo", {"bar":["baz", null, 1.0, 2]}]') - [u'foo', {u'bar': [u'baz', None, 1.0, 2]}] - >>> simplejson.loads('"\\"foo\\bar"') - u'"foo\x08ar' - >>> from StringIO import StringIO - >>> io = StringIO('["streaming API"]') - >>> simplejson.load(io) - [u'streaming API'] - -Specializing JSON object decoding:: - - >>> import simplejson - >>> def as_complex(dct): - ... if '__complex__' in dct: - ... return complex(dct['real'], dct['imag']) - ... return dct - ... - >>> simplejson.loads('{"__complex__": true, "real": 1, "imag": 2}', - ... object_hook=as_complex) - (1+2j) - >>> import decimal - >>> simplejson.loads('1.1', parse_float=decimal.Decimal) - Decimal("1.1") - -Extending JSONEncoder:: - - >>> import simplejson - >>> class ComplexEncoder(simplejson.JSONEncoder): - ... def default(self, obj): - ... if isinstance(obj, complex): - ... return [obj.real, obj.imag] - ... return simplejson.JSONEncoder.default(self, obj) - ... - >>> dumps(2 + 1j, cls=ComplexEncoder) - '[2.0, 1.0]' - >>> ComplexEncoder().encode(2 + 1j) - '[2.0, 1.0]' - >>> list(ComplexEncoder().iterencode(2 + 1j)) - ['[', '2.0', ', ', '1.0', ']'] - - -Using simplejson from the shell to validate and -pretty-print:: - - $ echo '{"json":"obj"}' | python -msimplejson.tool - { - "json": "obj" - } - $ echo '{ 1.2:3.4}' | python -msimplejson.tool - Expecting property name: line 1 column 2 (char 2) - -Note that the JSON produced by this module's default settings -is a subset of YAML, so it may be used as a serializer for that as well. -""" -__version__ = '1.9.2' -__all__ = [ - 'dump', 'dumps', 'load', 'loads', - 'JSONDecoder', 'JSONEncoder', -] - -if __name__ == '__main__': - import warnings - warnings.warn('python -msimplejson is deprecated, use python -msiplejson.tool', DeprecationWarning) - from simplejson.decoder import JSONDecoder - from simplejson.encoder import JSONEncoder -else: - from decoder import JSONDecoder - from encoder import JSONEncoder - -_default_encoder = JSONEncoder( - skipkeys=False, - ensure_ascii=True, - check_circular=True, - allow_nan=True, - indent=None, - separators=None, - encoding='utf-8', - default=None, -) - -def dump(obj, fp, skipkeys=False, ensure_ascii=True, check_circular=True, - allow_nan=True, cls=None, indent=None, separators=None, - encoding='utf-8', default=None, **kw): - """ - Serialize ``obj`` as a JSON formatted stream to ``fp`` (a - ``.write()``-supporting file-like object). - - If ``skipkeys`` is ``True`` then ``dict`` keys that are not basic types - (``str``, ``unicode``, ``int``, ``long``, ``float``, ``bool``, ``None``) - will be skipped instead of raising a ``TypeError``. - - If ``ensure_ascii`` is ``False``, then the some chunks written to ``fp`` - may be ``unicode`` instances, subject to normal Python ``str`` to - ``unicode`` coercion rules. Unless ``fp.write()`` explicitly - understands ``unicode`` (as in ``codecs.getwriter()``) this is likely - to cause an error. - - If ``check_circular`` is ``False``, then the circular reference check - for container types will be skipped and a circular reference will - result in an ``OverflowError`` (or worse). - - If ``allow_nan`` is ``False``, then it will be a ``ValueError`` to - serialize out of range ``float`` values (``nan``, ``inf``, ``-inf``) - in strict compliance of the JSON specification, instead of using the - JavaScript equivalents (``NaN``, ``Infinity``, ``-Infinity``). - - If ``indent`` is a non-negative integer, then JSON array elements and object - members will be pretty-printed with that indent level. An indent level - of 0 will only insert newlines. ``None`` is the most compact representation. - - If ``separators`` is an ``(item_separator, dict_separator)`` tuple - then it will be used instead of the default ``(', ', ': ')`` separators. - ``(',', ':')`` is the most compact JSON representation. - - ``encoding`` is the character encoding for str instances, default is UTF-8. - - ``default(obj)`` is a function that should return a serializable version - of obj or raise TypeError. The default simply raises TypeError. - - To use a custom ``JSONEncoder`` subclass (e.g. one that overrides the - ``.default()`` method to serialize additional types), specify it with - the ``cls`` kwarg. - """ - # cached encoder - if (skipkeys is False and ensure_ascii is True and - check_circular is True and allow_nan is True and - cls is None and indent is None and separators is None and - encoding == 'utf-8' and default is None and not kw): - iterable = _default_encoder.iterencode(obj) - else: - if cls is None: - cls = JSONEncoder - iterable = cls(skipkeys=skipkeys, ensure_ascii=ensure_ascii, - check_circular=check_circular, allow_nan=allow_nan, indent=indent, - separators=separators, encoding=encoding, - default=default, **kw).iterencode(obj) - # could accelerate with writelines in some versions of Python, at - # a debuggability cost - for chunk in iterable: - fp.write(chunk) - - -def dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True, - allow_nan=True, cls=None, indent=None, separators=None, - encoding='utf-8', default=None, **kw): - """ - Serialize ``obj`` to a JSON formatted ``str``. - - If ``skipkeys`` is ``True`` then ``dict`` keys that are not basic types - (``str``, ``unicode``, ``int``, ``long``, ``float``, ``bool``, ``None``) - will be skipped instead of raising a ``TypeError``. - - If ``ensure_ascii`` is ``False``, then the return value will be a - ``unicode`` instance subject to normal Python ``str`` to ``unicode`` - coercion rules instead of being escaped to an ASCII ``str``. - - If ``check_circular`` is ``False``, then the circular reference check - for container types will be skipped and a circular reference will - result in an ``OverflowError`` (or worse). - - If ``allow_nan`` is ``False``, then it will be a ``ValueError`` to - serialize out of range ``float`` values (``nan``, ``inf``, ``-inf``) in - strict compliance of the JSON specification, instead of using the - JavaScript equivalents (``NaN``, ``Infinity``, ``-Infinity``). - - If ``indent`` is a non-negative integer, then JSON array elements and - object members will be pretty-printed with that indent level. An indent - level of 0 will only insert newlines. ``None`` is the most compact - representation. - - If ``separators`` is an ``(item_separator, dict_separator)`` tuple - then it will be used instead of the default ``(', ', ': ')`` separators. - ``(',', ':')`` is the most compact JSON representation. - - ``encoding`` is the character encoding for str instances, default is UTF-8. - - ``default(obj)`` is a function that should return a serializable version - of obj or raise TypeError. The default simply raises TypeError. - - To use a custom ``JSONEncoder`` subclass (e.g. one that overrides the - ``.default()`` method to serialize additional types), specify it with - the ``cls`` kwarg. - """ - # cached encoder - if (skipkeys is False and ensure_ascii is True and - check_circular is True and allow_nan is True and - cls is None and indent is None and separators is None and - encoding == 'utf-8' and default is None and not kw): - return _default_encoder.encode(obj) - if cls is None: - cls = JSONEncoder - return cls( - skipkeys=skipkeys, ensure_ascii=ensure_ascii, - check_circular=check_circular, allow_nan=allow_nan, indent=indent, - separators=separators, encoding=encoding, default=default, - **kw).encode(obj) - - -_default_decoder = JSONDecoder(encoding=None, object_hook=None) - - -def load(fp, encoding=None, cls=None, object_hook=None, parse_float=None, - parse_int=None, parse_constant=None, **kw): - """ - Deserialize ``fp`` (a ``.read()``-supporting file-like object containing - a JSON document) to a Python object. - - If the contents of ``fp`` is encoded with an ASCII based encoding other - than utf-8 (e.g. latin-1), then an appropriate ``encoding`` name must - be specified. Encodings that are not ASCII based (such as UCS-2) are - not allowed, and should be wrapped with - ``codecs.getreader(fp)(encoding)``, or simply decoded to a ``unicode`` - object and passed to ``loads()`` - - ``object_hook`` is an optional function that will be called with the - result of any object literal decode (a ``dict``). The return value of - ``object_hook`` will be used instead of the ``dict``. This feature - can be used to implement custom decoders (e.g. JSON-RPC class hinting). - - To use a custom ``JSONDecoder`` subclass, specify it with the ``cls`` - kwarg. - """ - return loads(fp.read(), - encoding=encoding, cls=cls, object_hook=object_hook, - parse_float=parse_float, parse_int=parse_int, - parse_constant=parse_constant, **kw) - - -def loads(s, encoding=None, cls=None, object_hook=None, parse_float=None, - parse_int=None, parse_constant=None, **kw): - """ - Deserialize ``s`` (a ``str`` or ``unicode`` instance containing a JSON - document) to a Python object. - - If ``s`` is a ``str`` instance and is encoded with an ASCII based encoding - other than utf-8 (e.g. latin-1) then an appropriate ``encoding`` name - must be specified. Encodings that are not ASCII based (such as UCS-2) - are not allowed and should be decoded to ``unicode`` first. - - ``object_hook`` is an optional function that will be called with the - result of any object literal decode (a ``dict``). The return value of - ``object_hook`` will be used instead of the ``dict``. This feature - can be used to implement custom decoders (e.g. JSON-RPC class hinting). - - ``parse_float``, if specified, will be called with the string - of every JSON float to be decoded. By default this is equivalent to - float(num_str). This can be used to use another datatype or parser - for JSON floats (e.g. decimal.Decimal). - - ``parse_int``, if specified, will be called with the string - of every JSON int to be decoded. By default this is equivalent to - int(num_str). This can be used to use another datatype or parser - for JSON integers (e.g. float). - - ``parse_constant``, if specified, will be called with one of the - following strings: -Infinity, Infinity, NaN, null, true, false. - This can be used to raise an exception if invalid JSON numbers - are encountered. - - To use a custom ``JSONDecoder`` subclass, specify it with the ``cls`` - kwarg. - """ - if (cls is None and encoding is None and object_hook is None and - parse_int is None and parse_float is None and - parse_constant is None and not kw): - return _default_decoder.decode(s) - if cls is None: - cls = JSONDecoder - if object_hook is not None: - kw['object_hook'] = object_hook - if parse_float is not None: - kw['parse_float'] = parse_float - if parse_int is not None: - kw['parse_int'] = parse_int - if parse_constant is not None: - kw['parse_constant'] = parse_constant - return cls(encoding=encoding, **kw).decode(s) - - -# -# Compatibility cruft from other libraries -# - - -def decode(s): - """ - demjson, python-cjson API compatibility hook. Use loads(s) instead. - """ - import warnings - warnings.warn("simplejson.loads(s) should be used instead of decode(s)", - DeprecationWarning) - return loads(s) - - -def encode(obj): - """ - demjson, python-cjson compatibility hook. Use dumps(s) instead. - """ - import warnings - warnings.warn("simplejson.dumps(s) should be used instead of encode(s)", - DeprecationWarning) - return dumps(obj) - - -def read(s): - """ - jsonlib, JsonUtils, python-json, json-py API compatibility hook. - Use loads(s) instead. - """ - import warnings - warnings.warn("simplejson.loads(s) should be used instead of read(s)", - DeprecationWarning) - return loads(s) - - -def write(obj): - """ - jsonlib, JsonUtils, python-json, json-py API compatibility hook. - Use dumps(s) instead. - """ - import warnings - warnings.warn("simplejson.dumps(s) should be used instead of write(s)", - DeprecationWarning) - return dumps(obj) - - -if __name__ == '__main__': - import simplejson.tool - simplejson.tool.main() diff --git a/addon-sdk/source/python-lib/simplejson/decoder.py b/addon-sdk/source/python-lib/simplejson/decoder.py deleted file mode 100644 --- a/addon-sdk/source/python-lib/simplejson/decoder.py +++ /dev/null @@ -1,343 +0,0 @@ -""" -Implementation of JSONDecoder -""" -import re -import sys - -from simplejson.scanner import Scanner, pattern -try: - from simplejson._speedups import scanstring as c_scanstring -except ImportError: - pass - -FLAGS = re.VERBOSE | re.MULTILINE | re.DOTALL - -def _floatconstants(): - import struct - import sys - _BYTES = '7FF80000000000007FF0000000000000'.decode('hex') - if sys.byteorder != 'big': - _BYTES = _BYTES[:8][::-1] + _BYTES[8:][::-1] - nan, inf = struct.unpack('dd', _BYTES) - return nan, inf, -inf - -NaN, PosInf, NegInf = _floatconstants() - - -def linecol(doc, pos): - lineno = doc.count('\n', 0, pos) + 1 - if lineno == 1: - colno = pos - else: - colno = pos - doc.rindex('\n', 0, pos) - return lineno, colno - - -def errmsg(msg, doc, pos, end=None): - lineno, colno = linecol(doc, pos) - if end is None: - return '%s: line %d column %d (char %d)' % (msg, lineno, colno, pos) - endlineno, endcolno = linecol(doc, end) - return '%s: line %d column %d - line %d column %d (char %d - %d)' % ( - msg, lineno, colno, endlineno, endcolno, pos, end) - - -_CONSTANTS = { - '-Infinity': NegInf, - 'Infinity': PosInf, - 'NaN': NaN, - 'true': True, - 'false': False, - 'null': None, -} - -def JSONConstant(match, context, c=_CONSTANTS): - s = match.group(0) - fn = getattr(context, 'parse_constant', None) - if fn is None: - rval = c[s] - else: - rval = fn(s) - return rval, None -pattern('(-?Infinity|NaN|true|false|null)')(JSONConstant) - - -def JSONNumber(match, context): - match = JSONNumber.regex.match(match.string, *match.span()) - integer, frac, exp = match.groups() - if frac or exp: - fn = getattr(context, 'parse_float', None) or float - res = fn(integer + (frac or '') + (exp or '')) - else: - fn = getattr(context, 'parse_int', None) or int - res = fn(integer) - return res, None -pattern(r'(-?(?:0|[1-9]\d*))(\.\d+)?([eE][-+]?\d+)?')(JSONNumber) - - -STRINGCHUNK = re.compile(r'(.*?)(["\\\x00-\x1f])', FLAGS) -BACKSLASH = { - '"': u'"', '\\': u'\\', '/': u'/', - 'b': u'\b', 'f': u'\f', 'n': u'\n', 'r': u'\r', 't': u'\t', -} - -DEFAULT_ENCODING = "utf-8" - -def py_scanstring(s, end, encoding=None, strict=True, _b=BACKSLASH, _m=STRINGCHUNK.match): - if encoding is None: - encoding = DEFAULT_ENCODING - chunks = [] - _append = chunks.append - begin = end - 1 - while 1: - chunk = _m(s, end) - if chunk is None: - raise ValueError( - errmsg("Unterminated string starting at", s, begin)) - end = chunk.end() - content, terminator = chunk.groups() - if content: - if not isinstance(content, unicode): - content = unicode(content, encoding) - _append(content) - if terminator == '"': - break - elif terminator != '\\': - if strict: - raise ValueError(errmsg("Invalid control character %r at", s, end)) - else: - _append(terminator) - continue - try: - esc = s[end] - except IndexError: - raise ValueError( - errmsg("Unterminated string starting at", s, begin)) - if esc != 'u': - try: - m = _b[esc] - except KeyError: - raise ValueError( - errmsg("Invalid \\escape: %r" % (esc,), s, end)) - end += 1 - else: - esc = s[end + 1:end + 5] - next_end = end + 5 - msg = "Invalid \\uXXXX escape" - try: - if len(esc) != 4: - raise ValueError - uni = int(esc, 16) - if 0xd800 <= uni <= 0xdbff and sys.maxunicode > 65535: - msg = "Invalid \\uXXXX\\uXXXX surrogate pair" - if not s[end + 5:end + 7] == '\\u': - raise ValueError - esc2 = s[end + 7:end + 11] - if len(esc2) != 4: - raise ValueError - uni2 = int(esc2, 16) - uni = 0x10000 + (((uni - 0xd800) << 10) | (uni2 - 0xdc00)) - next_end += 6 - m = unichr(uni) - except ValueError: - raise ValueError(errmsg(msg, s, end)) - end = next_end - _append(m) - return u''.join(chunks), end - - -# Use speedup -try: - scanstring = c_scanstring -except NameError: - scanstring = py_scanstring - -def JSONString(match, context): - encoding = getattr(context, 'encoding', None) - strict = getattr(context, 'strict', True) - return scanstring(match.string, match.end(), encoding, strict) -pattern(r'"')(JSONString) - - -WHITESPACE = re.compile(r'\s*', FLAGS) - -def JSONObject(match, context, _w=WHITESPACE.match): - pairs = {} - s = match.string - end = _w(s, match.end()).end() - nextchar = s[end:end + 1] - # Trivial empty object - if nextchar == '}': - return pairs, end + 1 - if nextchar != '"': - raise ValueError(errmsg("Expecting property name", s, end)) - end += 1 - encoding = getattr(context, 'encoding', None) - strict = getattr(context, 'strict', True) - iterscan = JSONScanner.iterscan - while True: - key, end = scanstring(s, end, encoding, strict) - end = _w(s, end).end() - if s[end:end + 1] != ':': - raise ValueError(errmsg("Expecting : delimiter", s, end)) - end = _w(s, end + 1).end() - try: - value, end = iterscan(s, idx=end, context=context).next() - except StopIteration: - raise ValueError(errmsg("Expecting object", s, end)) - pairs[key] = value - end = _w(s, end).end() - nextchar = s[end:end + 1] - end += 1 - if nextchar == '}': - break - if nextchar != ',': - raise ValueError(errmsg("Expecting , delimiter", s, end - 1)) - end = _w(s, end).end() - nextchar = s[end:end + 1] - end += 1 - if nextchar != '"': - raise ValueError(errmsg("Expecting property name", s, end - 1)) - object_hook = getattr(context, 'object_hook', None) - if object_hook is not None: - pairs = object_hook(pairs) - return pairs, end -pattern(r'{')(JSONObject) - - -def JSONArray(match, context, _w=WHITESPACE.match): - values = [] - s = match.string - end = _w(s, match.end()).end() - # Look-ahead for trivial empty array - nextchar = s[end:end + 1] - if nextchar == ']': - return values, end + 1 - iterscan = JSONScanner.iterscan - while True: - try: - value, end = iterscan(s, idx=end, context=context).next() - except StopIteration: - raise ValueError(errmsg("Expecting object", s, end)) - values.append(value) - end = _w(s, end).end() - nextchar = s[end:end + 1] - end += 1 - if nextchar == ']': - break - if nextchar != ',': - raise ValueError(errmsg("Expecting , delimiter", s, end)) - end = _w(s, end).end() - return values, end -pattern(r'\[')(JSONArray) - - -ANYTHING = [ - JSONObject, - JSONArray, - JSONString, - JSONConstant, - JSONNumber, -] - -JSONScanner = Scanner(ANYTHING) - - -class JSONDecoder(object): - """ - Simple JSON decoder - - Performs the following translations in decoding by default: - - +---------------+-------------------+ - | JSON | Python | - +===============+===================+ - | object | dict | - +---------------+-------------------+ - | array | list | - +---------------+-------------------+ - | string | unicode | - +---------------+-------------------+ - | number (int) | int, long | - +---------------+-------------------+ - | number (real) | float | - +---------------+-------------------+ - | true | True | - +---------------+-------------------+ - | false | False | - +---------------+-------------------+ - | null | None | - +---------------+-------------------+ - - It also understands ``NaN``, ``Infinity``, and ``-Infinity`` as - their corresponding ``float`` values, which is outside the JSON spec. - """ - - _scanner = Scanner(ANYTHING) - __all__ = ['__init__', 'decode', 'raw_decode'] - - def __init__(self, encoding=None, object_hook=None, parse_float=None, - parse_int=None, parse_constant=None, strict=True): - """ - ``encoding`` determines the encoding used to interpret any ``str`` - objects decoded by this instance (utf-8 by default). It has no - effect when decoding ``unicode`` objects. - - Note that currently only encodings that are a superset of ASCII work, - strings of other encodings should be passed in as ``unicode``. - - ``object_hook``, if specified, will be called with the result - of every JSON object decoded and its return value will be used in - place of the given ``dict``. This can be used to provide custom - deserializations (e.g. to support JSON-RPC class hinting). - - ``parse_float``, if specified, will be called with the string - of every JSON float to be decoded. By default this is equivalent to - float(num_str). This can be used to use another datatype or parser - for JSON floats (e.g. decimal.Decimal). - - ``parse_int``, if specified, will be called with the string - of every JSON int to be decoded. By default this is equivalent to - int(num_str). This can be used to use another datatype or parser - for JSON integers (e.g. float). - - ``parse_constant``, if specified, will be called with one of the - following strings: -Infinity, Infinity, NaN, null, true, false. - This can be used to raise an exception if invalid JSON numbers - are encountered. - """ - self.encoding = encoding - self.object_hook = object_hook - self.parse_float = parse_float - self.parse_int = parse_int - self.parse_constant = parse_constant - self.strict = strict - - def decode(self, s, _w=WHITESPACE.match): - """ - Return the Python representation of ``s`` (a ``str`` or ``unicode`` - instance containing a JSON document) - """ - obj, end = self.raw_decode(s, idx=_w(s, 0).end()) - end = _w(s, end).end() - if end != len(s): - raise ValueError(errmsg("Extra data", s, end, len(s))) - return obj - - def raw_decode(self, s, **kw): - """ - Decode a JSON document from ``s`` (a ``str`` or ``unicode`` beginning - with a JSON document) and return a 2-tuple of the Python - representation and the index in ``s`` where the document ended. - - This can be used to decode a JSON document from a string that may - have extraneous data at the end. - """ - kw.setdefault('context', self) - try: - obj, end = self._scanner.iterscan(s, **kw).next() - except StopIteration: - raise ValueError("No JSON object could be decoded") - return obj, end - -__all__ = ['JSONDecoder'] diff --git a/addon-sdk/source/python-lib/simplejson/encoder.py b/addon-sdk/source/python-lib/simplejson/encoder.py deleted file mode 100644 --- a/addon-sdk/source/python-lib/simplejson/encoder.py +++ /dev/null @@ -1,395 +0,0 @@ -""" -Implementation of JSONEncoder -""" -import re - -try: - from simplejson._speedups import encode_basestring_ascii as c_encode_basestring_ascii -except ImportError: - pass - -ESCAPE = re.compile(r'[\x00-\x1f\\"\b\f\n\r\t]') -ESCAPE_ASCII = re.compile(r'([\\"]|[^\ -~])') -HAS_UTF8 = re.compile(r'[\x80-\xff]') -ESCAPE_DCT = { - '\\': '\\\\', - '"': '\\"', - '\b': '\\b', - '\f': '\\f', - '\n': '\\n', - '\r': '\\r', - '\t': '\\t', -} -for i in range(0x20): - ESCAPE_DCT.setdefault(chr(i), '\\u%04x' % (i,)) - -# Assume this produces an infinity on all machines (probably not guaranteed) -INFINITY = float('1e66666') -FLOAT_REPR = repr - -def floatstr(o, allow_nan=True): - """ - Check for specials. Note that this type of test is processor- and/or - platform-specific, so do tests which don't depend on the internals. - """ - if o != o: - text = 'NaN' - elif o == INFINITY: - text = 'Infinity' - elif o == -INFINITY: - text = '-Infinity' - else: - return FLOAT_REPR(o) - - if not allow_nan: - raise ValueError("Out of range float values are not JSON compliant: %r" - % (o,)) - - return text - - -def encode_basestring(s): - """ - Return a JSON representation of a Python string - """ - def replace(match): - return ESCAPE_DCT[match.group(0)] - return '"' + ESCAPE.sub(replace, s) + '"' - - -def py_encode_basestring_ascii(s): - if isinstance(s, str) and HAS_UTF8.search(s) is not None: - s = s.decode('utf-8') - def replace(match): - s = match.group(0) - try: - return ESCAPE_DCT[s] - except KeyError: - n = ord(s) - if n < 0x10000: - return '\\u%04x' % (n,) - else: - # surrogate pair - n -= 0x10000 - s1 = 0xd800 | ((n >> 10) & 0x3ff) - s2 = 0xdc00 | (n & 0x3ff) - return '\\u%04x\\u%04x' % (s1, s2) - return '"' + str(ESCAPE_ASCII.sub(replace, s)) + '"' - - -try: - encode_basestring_ascii = c_encode_basestring_ascii -except NameError: - encode_basestring_ascii = py_encode_basestring_ascii - - -class JSONEncoder(object): - """ - Extensible JSON encoder for Python data structures. - - Supports the following objects and types by default: - - +-------------------+---------------+ - | Python | JSON | - +===================+===============+ - | dict | object | - +-------------------+---------------+ - | list, tuple | array | - +-------------------+---------------+ - | str, unicode | string | - +-------------------+---------------+ - | int, long, float | number | - +-------------------+---------------+ - | True | true | - +-------------------+---------------+ - | False | false | - +-------------------+---------------+ - | None | null | - +-------------------+---------------+ - - To extend this to recognize other objects, subclass and implement a - ``.default()`` method with another method that returns a serializable - object for ``o`` if possible, otherwise it should call the superclass - implementation (to raise ``TypeError``). - """ - __all__ = ['__init__', 'default', 'encode', 'iterencode'] - item_separator = ', ' - key_separator = ': ' - def __init__(self, skipkeys=False, ensure_ascii=True, - check_circular=True, allow_nan=True, sort_keys=False, - indent=None, separators=None, encoding='utf-8', default=None): - """ - Constructor for JSONEncoder, with sensible defaults. - - If skipkeys is False, then it is a TypeError to attempt - encoding of keys that are not str, int, long, float or None. If - skipkeys is True, such items are simply skipped. - - If ensure_ascii is True, the output is guaranteed to be str - objects with all incoming unicode characters escaped. If - ensure_ascii is false, the output will be unicode object. - - If check_circular is True, then lists, dicts, and custom encoded - objects will be checked for circular references during encoding to - prevent an infinite recursion (which would cause an OverflowError). - Otherwise, no such check takes place. - - If allow_nan is True, then NaN, Infinity, and -Infinity will be - encoded as such. This behavior is not JSON specification compliant, - but is consistent with most JavaScript based encoders and decoders. - Otherwise, it will be a ValueError to encode such floats. - - If sort_keys is True, then the output of dictionaries will be - sorted by key; this is useful for regression tests to ensure - that JSON serializations can be compared on a day-to-day basis. - - If indent is a non-negative integer, then JSON array - elements and object members will be pretty-printed with that - indent level. An indent level of 0 will only insert newlines. - None is the most compact representation. - - If specified, separators should be a (item_separator, key_separator) - tuple. The default is (', ', ': '). To get the most compact JSON - representation you should specify (',', ':') to eliminate whitespace. - - If specified, default is a function that gets called for objects - that can't otherwise be serialized. It should return a JSON encodable - version of the object or raise a ``TypeError``. - - If encoding is not None, then all input strings will be - transformed into unicode using that encoding prior to JSON-encoding. - The default is UTF-8. - """ - - self.skipkeys = skipkeys - self.ensure_ascii = ensure_ascii - self.check_circular = check_circular - self.allow_nan = allow_nan - self.sort_keys = sort_keys - self.indent = indent - self.current_indent_level = 0 - if separators is not None: - self.item_separator, self.key_separator = separators - if default is not None: - self.default = default - self.encoding = encoding - - def _newline_indent(self): - """ - Indent lines by level - """ - return '\n' + (' ' * (self.indent * self.current_indent_level)) - - def _iterencode_list(self, lst, markers=None): - """ - Encoding lists, yielding by level - """ - if not lst: - yield '[]' - return - if markers is not None: - markerid = id(lst) - if markerid in markers: - raise ValueError("Circular reference detected") - markers[markerid] = lst - yield '[' - if self.indent is not None: - self.current_indent_level += 1 - newline_indent = self._newline_indent() - separator = self.item_separator + newline_indent - yield newline_indent - else: - newline_indent = None - separator = self.item_separator - first = True - for value in lst: - if first: - first = False - else: - yield separator - for chunk in self._iterencode(value, markers): - yield chunk - if newline_indent is not None: - self.current_indent_level -= 1 - yield self._newline_indent() - yield ']' - if markers is not None: - del markers[markerid] - - def _iterencode_dict(self, dct, markers=None): - """ - Encoding dictionaries, yielding by level - """ - if not dct: - yield '{}' - return - if markers is not None: - markerid = id(dct) - if markerid in markers: - raise ValueError("Circular reference detected") - markers[markerid] = dct - yield '{' - key_separator = self.key_separator - if self.indent is not None: - self.current_indent_level += 1 - newline_indent = self._newline_indent() - item_separator = self.item_separator + newline_indent - yield newline_indent - else: - newline_indent = None - item_separator = self.item_separator - first = True - if self.ensure_ascii: - encoder = encode_basestring_ascii - else: - encoder = encode_basestring - allow_nan = self.allow_nan - if self.sort_keys: - keys = dct.keys() - keys.sort() - items = [(k, dct[k]) for k in keys] - else: - items = dct.iteritems() - _encoding = self.encoding - _do_decode = (_encoding is not None - and not (_encoding == 'utf-8')) - for key, value in items: - if isinstance(key, str): - if _do_decode: - key = key.decode(_encoding) - elif isinstance(key, basestring): - pass - # JavaScript is weakly typed for these, so it makes sense to - # also allow them. Many encoders seem to do something like this. - elif isinstance(key, float): - key = floatstr(key, allow_nan) - elif isinstance(key, (int, long)): - key = str(key) - elif key is True: - key = 'true' - elif key is False: - key = 'false' - elif key is None: - key = 'null' - elif self.skipkeys: - continue - else: - raise TypeError("key %r is not a string" % (key,)) - if first: - first = False - else: - yield item_separator - yield encoder(key) - yield key_separator - for chunk in self._iterencode(value, markers): - yield chunk - if newline_indent is not None: - self.current_indent_level -= 1 - yield self._newline_indent() - yield '}' - if markers is not None: - del markers[markerid] - - def _iterencode(self, o, markers=None): - if isinstance(o, basestring): - if self.ensure_ascii: - encoder = encode_basestring_ascii - else: - encoder = encode_basestring - _encoding = self.encoding - if (_encoding is not None and isinstance(o, str) - and not (_encoding == 'utf-8')): - o = o.decode(_encoding) - yield encoder(o) - elif o is None: - yield 'null' - elif o is True: - yield 'true' - elif o is False: - yield 'false' - elif isinstance(o, (int, long)): - yield str(o) - elif isinstance(o, float): - yield floatstr(o, self.allow_nan) - elif isinstance(o, (list, tuple)): - for chunk in self._iterencode_list(o, markers): - yield chunk - elif isinstance(o, dict): - for chunk in self._iterencode_dict(o, markers): - yield chunk - else: - if markers is not None: - markerid = id(o) - if markerid in markers: - raise ValueError("Circular reference detected") - markers[markerid] = o - for chunk in self._iterencode_default(o, markers): - yield chunk - if markers is not None: - del markers[markerid] - - def _iterencode_default(self, o, markers=None): - newobj = self.default(o) - return self._iterencode(newobj, markers) - - def default(self, o): - """ - Implement this method in a subclass such that it returns - a serializable object for ``o``, or calls the base implementation - (to raise a ``TypeError``). - - For example, to support arbitrary iterators, you could - implement default like this:: - - def default(self, o): - try: - iterable = iter(o) - except TypeError: - pass - else: - return list(iterable) - return JSONEncoder.default(self, o) - """ - raise TypeError("%r is not JSON serializable" % (o,)) - - def encode(self, o): - """ - Return a JSON string representation of a Python data structure. - - >>> JSONEncoder().encode({"foo": ["bar", "baz"]}) - '{"foo": ["bar", "baz"]}' - """ - # This is for extremely simple cases and benchmarks. - if isinstance(o, basestring): - if isinstance(o, str): - _encoding = self.encoding - if (_encoding is not None - and not (_encoding == 'utf-8')): - o = o.decode(_encoding) - if self.ensure_ascii: - return encode_basestring_ascii(o) - else: - return encode_basestring(o) - # This doesn't pass the iterator directly to ''.join() because the - # exceptions aren't as detailed. The list call should be roughly - # equivalent to the PySequence_Fast that ''.join() would do. - chunks = list(self.iterencode(o)) - return ''.join(chunks) - - def iterencode(self, o): - """ - Encode the given object and yield each string - representation as available. - - For example:: - - for chunk in JSONEncoder().iterencode(bigobject): - mysocket.write(chunk) - """ - if self.check_circular: - markers = {} - else: - markers = None - return self._iterencode(o, markers) - -__all__ = ['JSONEncoder'] diff --git a/addon-sdk/source/python-lib/simplejson/scanner.py b/addon-sdk/source/python-lib/simplejson/scanner.py deleted file mode 100644 --- a/addon-sdk/source/python-lib/simplejson/scanner.py +++ /dev/null @@ -1,67 +0,0 @@ -""" -Iterator based sre token scanner -""" -import re -from re import VERBOSE, MULTILINE, DOTALL -import sre_parse -import sre_compile -import sre_constants -from sre_constants import BRANCH, SUBPATTERN - -__all__ = ['Scanner', 'pattern'] - -FLAGS = (VERBOSE | MULTILINE | DOTALL) - -class Scanner(object): - def __init__(self, lexicon, flags=FLAGS): - self.actions = [None] - # Combine phrases into a compound pattern - s = sre_parse.Pattern() - s.flags = flags - p = [] - for idx, token in enumerate(lexicon): - phrase = token.pattern - try: - subpattern = sre_parse.SubPattern(s, - [(SUBPATTERN, (idx + 1, sre_parse.parse(phrase, flags)))]) - except sre_constants.error: - raise - p.append(subpattern) - self.actions.append(token) - - s.groups = len(p) + 1 # NOTE(guido): Added to make SRE validation work - p = sre_parse.SubPattern(s, [(BRANCH, (None, p))]) - self.scanner = sre_compile.compile(p) - - def iterscan(self, string, idx=0, context=None): - """ - Yield match, end_idx for each match - """ - match = self.scanner.scanner(string, idx).match - actions = self.actions - lastend = idx - end = len(string) - while True: - m = match() - if m is None: - break - matchbegin, matchend = m.span() - if lastend == matchend: - break - action = actions[m.lastindex] - if action is not None: - rval, next_pos = action(m, context) - if next_pos is not None and next_pos != matchend: - # "fast forward" the scanner - matchend = next_pos - match = self.scanner.scanner(string, matchend).match - yield rval, matchend - lastend = matchend - - -def pattern(pattern, flags=FLAGS): - def decorator(fn): - fn.pattern = pattern - fn.regex = re.compile(pattern, flags) - return fn - return decorator \ No newline at end of file diff --git a/addon-sdk/source/python-lib/simplejson/tool.py b/addon-sdk/source/python-lib/simplejson/tool.py deleted file mode 100644 --- a/addon-sdk/source/python-lib/simplejson/tool.py +++ /dev/null @@ -1,44 +0,0 @@ -r""" -Using simplejson from the shell to validate and -pretty-print:: - - $ echo '{"json":"obj"}' | python -msimplejson - { - "json": "obj" - } - $ echo '{ 1.2:3.4}' | python -msimplejson - Expecting property name: line 1 column 2 (char 2) - -Note that the JSON produced by this module's default settings -is a subset of YAML, so it may be used as a serializer for that as well. -""" -import simplejson - -# -# Pretty printer: -# curl http://mochikit.com/examples/ajax_tables/domains.json | python -msimplejson.tool -# - -def main(): - import sys - if len(sys.argv) == 1: - infile = sys.stdin - outfile = sys.stdout - elif len(sys.argv) == 2: - infile = open(sys.argv[1], 'rb') - outfile = sys.stdout - elif len(sys.argv) == 3: - infile = open(sys.argv[1], 'rb') - outfile = open(sys.argv[2], 'wb') - else: - raise SystemExit("%s [infile [outfile]]" % (sys.argv[0],)) - try: - obj = simplejson.load(infile) - except ValueError, e: - raise SystemExit(e) - simplejson.dump(obj, outfile, sort_keys=True, indent=4) - outfile.write('\n') - - -if __name__ == '__main__': - main() diff --git a/build/mach_initialize.py b/build/mach_initialize.py --- a/build/mach_initialize.py +++ b/build/mach_initialize.py @@ -32,17 +32,16 @@ MOZBUILD_STATE_PATH environment variable use, and run Mach again. Press ENTER/RETURN to continue or CTRL+c to abort. '''.strip() # Individual files providing mach commands. MACH_MODULES = [ - 'addon-sdk/mach_commands.py', 'build/valgrind/mach_commands.py', 'devtools/shared/css/generated/mach_commands.py', 'dom/bindings/mach_commands.py', 'js/src/devtools/rootAnalysis/mach_commands.py', 'layout/tools/reftest/mach_commands.py', 'python/mach/mach/commands/commandinfo.py', 'python/mach/mach/commands/settings.py', 'python/mach_commands.py',