mirror of
https://github.com/cappuccino/cappuccino.git
synced 2026-08-25 04:57:03 +00:00
Further migration from file paths to CFURLs.
Reviewed by me.
This commit is contained in:
@@ -113,7 +113,7 @@ var CPBundlesForPaths = { };
|
||||
|
||||
- (id)objectForInfoDictionaryKey:(CPString)aKey
|
||||
{
|
||||
return _bundle.valueForInfoDictionary(aKey);
|
||||
return _bundle.valueForInfoDictionaryKey(aKey);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
+36
-428
@@ -29,19 +29,23 @@ CPURLCustomIconKey = @"CPURLCustomIconKey";
|
||||
|
||||
@implementation CPURL : CPObject
|
||||
{
|
||||
CPURL _base @accessors(readonly, property=baseURL);
|
||||
CPString _relative @accessors(readonly, property=relativeString);
|
||||
|
||||
CPDictionary _resourceValues;
|
||||
}
|
||||
|
||||
- (id)initWithScheme:(CPString)scheme host:(CPString)host path:(CPString)path
|
||||
+ (id)alloc
|
||||
{
|
||||
var uri = new URI();
|
||||
uri.scheme = scheme;
|
||||
uri.authority = host;
|
||||
uri.path = path;
|
||||
[self initWithString:uri.toString()];
|
||||
return new CFURL();
|
||||
}
|
||||
|
||||
- (id)init
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (id)initWithScheme:(CPString)aScheme host:(CPString)aHost path:(CPString)aPath
|
||||
{
|
||||
var URLString = (aScheme ? aScheme + ":" : "") + (aHost ? aHost + "//" : "") + (aPath || "");
|
||||
|
||||
return [self initWithString:URLString];
|
||||
}
|
||||
|
||||
- (id)initWithString:(CPString)URLString
|
||||
@@ -54,51 +58,35 @@ CPURLCustomIconKey = @"CPURLCustomIconKey";
|
||||
return [[self alloc] initWithString:URLString];
|
||||
}
|
||||
|
||||
- (id)initWithString:(CPString)URLString relativeToURL:(CPURL)baseURL
|
||||
- (id)initWithString:(CPString)URLString relativeToURL:(CPURL)aBaseURL
|
||||
{
|
||||
if (!URI_RE.test(URLString))
|
||||
return nil;
|
||||
|
||||
if (self)
|
||||
{
|
||||
_base = baseURL;
|
||||
_relative = URLString;
|
||||
_resourceValues = [CPDictionary dictionary];
|
||||
}
|
||||
|
||||
return self;
|
||||
return new CFURL(URLString, aBaseURL);
|
||||
}
|
||||
|
||||
+ (id)URLWithString:(CPString)URLString relativeToURL:(CPURL)baseURL
|
||||
+ (id)URLWithString:(CPString)URLString relativeToURL:(CPURL)aBaseURL
|
||||
{
|
||||
return [[self alloc] initWithString:URLString relativeToURL:baseURL];
|
||||
return [[self alloc] initWithString:URLString relativeToURL:aBaseURL];
|
||||
}
|
||||
|
||||
- (CPURL)absoluteURL
|
||||
{
|
||||
var absStr = [self absoluteString];
|
||||
|
||||
if (absStr !== _relative)
|
||||
return [[CPURL alloc] initWithString:absStr];
|
||||
|
||||
return self;
|
||||
return self.absoluteURL();
|
||||
}
|
||||
|
||||
- (CPString)absoluteString
|
||||
{
|
||||
return resolve([_base absoluteString] || "", _relative);
|
||||
return self.absoluteString();
|
||||
}
|
||||
|
||||
// if absolute, returns same as absoluteString
|
||||
- (CPString)relativeString
|
||||
{
|
||||
return _relative;
|
||||
return self.string();
|
||||
}
|
||||
|
||||
- (CPString)path
|
||||
{
|
||||
var str = [self absoluteString];
|
||||
return URI_RE.test(str) ? (parse(str).path || nil) : nil;
|
||||
return [self absoluteString].path();
|
||||
}
|
||||
|
||||
// if absolute, returns the same as path
|
||||
@@ -107,11 +95,9 @@ CPURLCustomIconKey = @"CPURLCustomIconKey";
|
||||
return URI_RE.test(_relative) ? (parse(_relative).path || nil) : nil;
|
||||
}
|
||||
|
||||
|
||||
- (CPString)scheme
|
||||
{
|
||||
var str = [self absoluteString];
|
||||
return URI_RE.test(str) ? (parse(str).protocol || nil) : nil;
|
||||
return self.scheme();
|
||||
}
|
||||
|
||||
- (CPString)user
|
||||
@@ -164,15 +150,12 @@ CPURLCustomIconKey = @"CPURLCustomIconKey";
|
||||
|
||||
- (CPString)lastPathComponent
|
||||
{
|
||||
var path = [self path];
|
||||
return path ? path.split("/").pop() : nil;
|
||||
return [self absoluteURL].lastPathComponent();
|
||||
}
|
||||
|
||||
- (CPString)pathExtension
|
||||
{
|
||||
var path = [self path],
|
||||
ext = path.match(/\.(\w+)$/);
|
||||
return ext ? ext[1] : "";
|
||||
return self.pathExtension();
|
||||
}
|
||||
|
||||
- (CPURL)standardizedURL
|
||||
@@ -192,413 +175,38 @@ CPURLCustomIconKey = @"CPURLCustomIconKey";
|
||||
|
||||
- (id)resourceValueForKey:(CPString)aKey
|
||||
{
|
||||
return [_resourceValues objectForKey:aKey];
|
||||
return self.resourcePropertyForKey(aKey);
|
||||
}
|
||||
|
||||
- (id)setResourceValue:(id)anObject forKey:(CPString)aKey
|
||||
{
|
||||
[_resourceValues setObject:anObject forKey:aKey];
|
||||
return self.setResourcePropertyForKey(aKey, anObject);
|
||||
}
|
||||
|
||||
- (CPString)staticResourceData
|
||||
{
|
||||
// FIXME: This probably shouldn't go through CFBundle for no reason.
|
||||
return CFBundle.dataContentsAtPath([self path]);
|
||||
return self.staticResourceData();
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
var CPURLURLStringKey = @"CPURLURLStringKey",
|
||||
CPURLBaseURLKey = @"CPURLBaseURLKey";
|
||||
|
||||
@implementation CPURL (CPCoding)
|
||||
|
||||
- (id)initWithCoder:(CPCoder)aCoder
|
||||
{
|
||||
_base = [aCoder decodeObjectForKey:"CPURLBaseKey"];
|
||||
_relative = [aCoder decodeObjectForKey:"CPURLRelativeKey"];
|
||||
return self;
|
||||
return [self initWithURLString:[aCoder decodeObjectForKey:CPURLURLStringKey]
|
||||
baseURL:[aCoder decodeObjectForKey:CPURLBaseURLKey]];
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(CPCoder)aCoder
|
||||
{
|
||||
[aCoder encodeObject:_base forKey:"CPURLBaseKey"];
|
||||
[aCoder encodeObject:_relative forKey:"CPURLRelativeKey"];
|
||||
[aCoder encodeObject:_baseURL forKey:CPURLBaseURLKey];
|
||||
[aCoder encodeObject:_string forKey:CPURLURLStringKey];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
// original code: http://code.google.com/p/js-uri/
|
||||
|
||||
// Based on the regex in RFC2396 Appendix B.
|
||||
var URI_RE = /^(?:([^:\/?\#]+):)?(?:\/\/([^\/?\#]*))?([^?\#]*)(?:\?([^\#]*))?(?:\#(.*))?/;
|
||||
|
||||
/**
|
||||
* Uniform Resource Identifier (URI) - RFC3986
|
||||
*/
|
||||
var URI = function(str) {
|
||||
if (!str) str = "";
|
||||
var result = str.match(URI_RE);
|
||||
this.scheme = result[1] || null;
|
||||
this.authority = result[2] || null;
|
||||
this.path = result[3] || null;
|
||||
this.query = result[4] || null;
|
||||
this.fragment = result[5] || null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the URI to a String.
|
||||
*/
|
||||
URI.prototype.toString = function () {
|
||||
var str = "";
|
||||
|
||||
if (this.scheme)
|
||||
str += this.scheme + ":";
|
||||
|
||||
if (this.authority)
|
||||
str += "//" + this.authority;
|
||||
|
||||
if (this.path)
|
||||
str += this.path;
|
||||
|
||||
if (this.query)
|
||||
str += "?" + this.query;
|
||||
|
||||
if (this.fragment)
|
||||
str += "#" + this.fragment;
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
var parse = function(uri) {
|
||||
return new URI(uri);
|
||||
}
|
||||
|
||||
var unescape = function(str, plus) {
|
||||
return decodeURI(str).replace(/\+/g, " ");
|
||||
}
|
||||
|
||||
var unescapeComponent = function(str, plus) {
|
||||
return decodeURIComponent(str).replace(/\+/g, " ");
|
||||
}
|
||||
|
||||
// from Chiron's HTTP module:
|
||||
|
||||
/**** keys
|
||||
members of a parsed URI object.
|
||||
*/
|
||||
var keys = [
|
||||
"url",
|
||||
"protocol",
|
||||
"authorityRoot",
|
||||
"authority",
|
||||
"userInfo",
|
||||
"user",
|
||||
"password",
|
||||
"domain",
|
||||
"domains",
|
||||
"port",
|
||||
"path",
|
||||
"root",
|
||||
"directory",
|
||||
"directories",
|
||||
"file",
|
||||
"query",
|
||||
"anchor"
|
||||
];
|
||||
|
||||
/**** expressionKeys
|
||||
members of a parsed URI object that you get
|
||||
from evaluting the strict regular expression.
|
||||
*/
|
||||
var expressionKeys = [
|
||||
"url",
|
||||
"protocol",
|
||||
"authorityRoot",
|
||||
"authority",
|
||||
"userInfo",
|
||||
"user",
|
||||
"password",
|
||||
"domain",
|
||||
"port",
|
||||
"path",
|
||||
"root",
|
||||
"directory",
|
||||
"file",
|
||||
"query",
|
||||
"anchor"
|
||||
];
|
||||
|
||||
/**** strictExpression
|
||||
*/
|
||||
var strictExpression = new RegExp( /* url */
|
||||
"^" +
|
||||
"(?:" +
|
||||
"([^:/?#]+):" + /* protocol */
|
||||
")?" +
|
||||
"(?:" +
|
||||
"(//)" + /* authorityRoot */
|
||||
"(" + /* authority */
|
||||
"(?:" +
|
||||
"(" + /* userInfo */
|
||||
"([^:@]*)" + /* user */
|
||||
":?" +
|
||||
"([^:@]*)" + /* password */
|
||||
")?" +
|
||||
"@" +
|
||||
")?" +
|
||||
"([^:/?#]*)" + /* domain */
|
||||
"(?::(\\d*))?" + /* port */
|
||||
")" +
|
||||
")?" +
|
||||
"(" + /* path */
|
||||
"(/?)" + /* root */
|
||||
"((?:[^?#/]*/)*)" +
|
||||
"([^?#]*)" + /* file */
|
||||
")" +
|
||||
"(?:\\?([^#]*))?" + /* query */
|
||||
"(?:#(.*))?" /*anchor */
|
||||
);
|
||||
|
||||
/**** Parser
|
||||
returns a URI parser function given
|
||||
a regular expression that renders
|
||||
`expressionKeys` and returns an `Object`
|
||||
mapping all `keys` to values.
|
||||
*/
|
||||
var Parser = function (expression) {
|
||||
return function (url) {
|
||||
if (typeof url == "undefined")
|
||||
throw new Error("HttpError: URL is undefined");
|
||||
if (typeof url != "string") return new Object(url);
|
||||
|
||||
var items = {};
|
||||
var parts = expression.exec(url);
|
||||
|
||||
for (var i = 0; i < parts.length; i++) {
|
||||
items[expressionKeys[i]] = parts[i] ? parts[i] : "";
|
||||
}
|
||||
|
||||
items.root = (items.root || items.authorityRoot) ? '/' : '';
|
||||
|
||||
items.directories = items.directory.split("/");
|
||||
if (items.directories[items.directories.length - 1] == "") {
|
||||
items.directories.pop();
|
||||
}
|
||||
|
||||
/* normalize */
|
||||
var directories = [];
|
||||
for (var i = 0; i < items.directories.length; i++) {
|
||||
var directory = items.directories[i];
|
||||
if (directory == '.') {
|
||||
} else if (directory == '..') {
|
||||
if (directories.length && directories[directories.length - 1] != '..')
|
||||
directories.pop();
|
||||
else
|
||||
directories.push('..');
|
||||
} else {
|
||||
directories.push(directory);
|
||||
}
|
||||
}
|
||||
items.directories = directories;
|
||||
|
||||
items.domains = items.domain.split(".");
|
||||
|
||||
return items;
|
||||
};
|
||||
};
|
||||
|
||||
/**** parse
|
||||
a strict URI parser.
|
||||
*/
|
||||
var parse = Parser(strictExpression);
|
||||
|
||||
/**** format
|
||||
accepts a parsed URI object and returns
|
||||
the corresponding string.
|
||||
*/
|
||||
var format = function (object) {
|
||||
if (typeof(object) == 'undefined')
|
||||
throw new Error("UrlError: URL undefined for urls#format");
|
||||
if (object instanceof String || typeof(object) == 'string')
|
||||
return object;
|
||||
var domain =
|
||||
object.domains ?
|
||||
object.domains.join(".") :
|
||||
object.domain;
|
||||
var userInfo = (
|
||||
object.user ||
|
||||
object.password
|
||||
) ?
|
||||
(
|
||||
(object.user || "") +
|
||||
(object.password ? ":" + object.password : "")
|
||||
) :
|
||||
object.userInfo;
|
||||
var authority = (
|
||||
userInfo ||
|
||||
domain ||
|
||||
object.port
|
||||
) ? (
|
||||
(userInfo ? userInfo + "@" : "") +
|
||||
(domain || "") +
|
||||
(object.port ? ":" + object.port : "")
|
||||
) :
|
||||
object.authority;
|
||||
var directory =
|
||||
object.directories ?
|
||||
object.directories.join("/") :
|
||||
object.directory;
|
||||
var path =
|
||||
directory || object.file ?
|
||||
(
|
||||
(directory ? directory + "/" : "") +
|
||||
(object.file || "")
|
||||
) :
|
||||
object.path;
|
||||
return (
|
||||
(object.protocol ? object.protocol + ":" : "") +
|
||||
(authority ? "//" + authority : "") +
|
||||
(object.root || (authority && path) ? "/" : "") +
|
||||
(path ? path : "") +
|
||||
(object.query ? "?" + object.query : "") +
|
||||
(object.anchor ? "#" + object.anchor : "")
|
||||
) || object.url || "";
|
||||
};
|
||||
|
||||
/**** resolveObject
|
||||
returns an object representing a URL resolved from
|
||||
a relative location and a source location.
|
||||
*/
|
||||
var resolveObject = function (source, relative) {
|
||||
if (!source)
|
||||
return relative;
|
||||
|
||||
source = parse(source);
|
||||
relative = parse(relative);
|
||||
|
||||
if (relative.url == "")
|
||||
return source;
|
||||
|
||||
delete source.url;
|
||||
delete source.authority;
|
||||
delete source.domain;
|
||||
delete source.userInfo;
|
||||
delete source.path;
|
||||
delete source.directory;
|
||||
|
||||
if (
|
||||
relative.protocol && relative.protocol != source.protocol ||
|
||||
relative.authority && relative.authority != source.authority
|
||||
) {
|
||||
source = relative;
|
||||
} else {
|
||||
if (relative.root) {
|
||||
source.directories = relative.directories;
|
||||
} else {
|
||||
|
||||
var directories = relative.directories;
|
||||
for (var i = 0; i < directories.length; i++) {
|
||||
var directory = directories[i];
|
||||
if (directory == ".") {
|
||||
} else if (directory == "..") {
|
||||
if (source.directories.length) {
|
||||
source.directories.pop();
|
||||
} else {
|
||||
source.directories.push('..');
|
||||
}
|
||||
} else {
|
||||
source.directories.push(directory);
|
||||
}
|
||||
}
|
||||
|
||||
if (relative.file == ".") {
|
||||
relative.file = "";
|
||||
} else if (relative.file == "..") {
|
||||
source.directories.pop();
|
||||
relative.file = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (relative.root)
|
||||
source.root = relative.root;
|
||||
if (relative.protcol)
|
||||
source.protocol = relative.protocol;
|
||||
if (!(!relative.path && relative.anchor))
|
||||
source.file = relative.file;
|
||||
source.query = relative.query;
|
||||
source.anchor = relative.anchor;
|
||||
|
||||
return source;
|
||||
};
|
||||
|
||||
/**** relativeObject
|
||||
returns an object representing a relative URL to
|
||||
a given target URL from a source URL.
|
||||
*/
|
||||
var relativeObject = function (source, target) {
|
||||
target = parse(target);
|
||||
source = parse(source);
|
||||
|
||||
delete target.url;
|
||||
|
||||
if (
|
||||
target.protocol == source.protocol &&
|
||||
target.authority == source.authority
|
||||
) {
|
||||
delete target.protocol;
|
||||
delete target.authority;
|
||||
delete target.userInfo;
|
||||
delete target.user;
|
||||
delete target.password;
|
||||
delete target.domain;
|
||||
delete target.domains;
|
||||
delete target.port;
|
||||
if (
|
||||
!!target.root == !!source.root && !(
|
||||
target.root &&
|
||||
target.directories[0] != source.directories[0]
|
||||
)
|
||||
) {
|
||||
delete target.path;
|
||||
delete target.root;
|
||||
delete target.directory;
|
||||
while (
|
||||
source.directories.length &&
|
||||
target.directories.length &&
|
||||
target.directories[0] == source.directories[0]
|
||||
) {
|
||||
target.directories.shift();
|
||||
source.directories.shift();
|
||||
}
|
||||
while (source.directories.length) {
|
||||
source.directories.shift();
|
||||
target.directories.unshift('..');
|
||||
}
|
||||
|
||||
if (!target.root && !target.directories.length && !target.file && source.file)
|
||||
target.directories.push('.');
|
||||
|
||||
if (source.file == target.file)
|
||||
delete target.file;
|
||||
if (source.query == target.query)
|
||||
delete target.query;
|
||||
if (source.anchor == target.anchor)
|
||||
delete target.anchor;
|
||||
}
|
||||
}
|
||||
|
||||
return target;
|
||||
};
|
||||
|
||||
/**** resolve
|
||||
returns a URL resovled to a relative URL from a source URL.
|
||||
*/
|
||||
var resolve = function (source, relative) {
|
||||
return format(resolveObject(source, relative));
|
||||
};
|
||||
|
||||
/**** relative
|
||||
returns a relative URL to a target from a source.
|
||||
*/
|
||||
var relative = function (source, target) {
|
||||
return format(relativeObject(source, target));
|
||||
};
|
||||
CFURL.prototype.isa = [CPURL class];
|
||||
|
||||
+33
-24
@@ -20,42 +20,52 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
var cwd = FILE.cwd(),
|
||||
rootResource = new StaticResource("", NULL, YES, cwd !== "/");
|
||||
|
||||
StaticResource.root = rootResource;
|
||||
#ifdef COMMONJS
|
||||
var mainBundleURL = new CFURL("file:" + require("file").cwd());
|
||||
#elif defined(BROWSER)
|
||||
// To determine where our application lives, start with the current URL of the page.
|
||||
var pageURL = new CFURL(window.location.href),
|
||||
|
||||
#ifdef BROWSER
|
||||
// Look for any <base> tags and choose the last one (which is the one that will take effect).
|
||||
DOMBaseElements = document.getElementsByTagName("base"),
|
||||
DOMBaseElementsCount = DOMBaseElements.length;
|
||||
|
||||
if (DOMBaseElementsCount > 0)
|
||||
{
|
||||
var DOMBaseElement = DOMBaseElements[DOMBaseElementsCount - 1],
|
||||
DOMBaseElementHref = DOMBaseElement && DOMBaseElement.getAttribute("href");
|
||||
|
||||
// If we have one, use it instead.
|
||||
if (DOMBaseElementHref)
|
||||
pageURL = new CFURL(DOMBaseElementHref, pageURL);
|
||||
}
|
||||
|
||||
// Turn the main file into a URL.
|
||||
var mainFileURL = new CFURL(window.OBJJ_MAIN_FILE || "main.j"),
|
||||
|
||||
// The main bundle is the containing folder of the main file.
|
||||
mainBundleURL = new CFURL(".", new CFURL(mainFileURL, pageURL)).absoluteURL();
|
||||
|
||||
StaticResource.resourceAtURL(new CFURL("..", mainBundleURL).absoluteURL(), YES);
|
||||
|
||||
exports.bootstrap = function()
|
||||
{
|
||||
if (rootResource.isResolved())
|
||||
{
|
||||
rootResource.nodeAtSubPath(FILE.dirname(cwd), YES);
|
||||
resolveCWD();
|
||||
}
|
||||
else
|
||||
{
|
||||
rootResource.resolve();
|
||||
rootResource.addEventListener("resolve", resolveCWD);
|
||||
}
|
||||
resolveMainBundleURL();
|
||||
}
|
||||
|
||||
function resolveCWD()
|
||||
function resolveMainBundleURL()
|
||||
{
|
||||
rootResource.resolveSubPath(cwd, YES, function(/*StaticResource*/ aResource)
|
||||
StaticResource.resolveResourceAtURL(mainBundleURL, YES, function(/*StaticResource*/ aResource)
|
||||
{
|
||||
var includePaths = StaticResource.includePaths(),
|
||||
var includeURLs = StaticResource.includeURLs(),
|
||||
index = 0,
|
||||
count = includePaths.length;
|
||||
count = includeURLs.length;
|
||||
|
||||
for (; index < count; ++index)
|
||||
aResource.nodeAtSubPath(FILE.normal(includePaths[index]), YES);
|
||||
aResource.resourceAtURL(includeURLs[index], YES);
|
||||
|
||||
if (typeof OBJJ_MAIN_FILE === "undefined")
|
||||
OBJJ_MAIN_FILE = "main.j";
|
||||
|
||||
Executable.fileImporterForPath(cwd)(OBJJ_MAIN_FILE || "main.j", YES, function()
|
||||
Executable.fileImporterForURL(mainBundleURL)(mainFileURL, YES, function()
|
||||
{
|
||||
afterDocumentLoad(main);
|
||||
});
|
||||
@@ -81,7 +91,6 @@ afterDocumentLoad(function()
|
||||
documentLoaded = YES;
|
||||
});
|
||||
|
||||
|
||||
if (typeof OBJJ_AUTO_BOOTSTRAP === "undefined" || OBJJ_AUTO_BOOTSTRAP)
|
||||
exports.bootstrap();
|
||||
|
||||
|
||||
+144
-127
@@ -27,25 +27,27 @@ var CFBundleUnloaded = 0,
|
||||
CFBundleLoadingSpritedImages = 1 << 3,
|
||||
CFBundleLoaded = 1 << 4;
|
||||
|
||||
var CFBundlesForPaths = { },
|
||||
CFBundlesForClasses = { },
|
||||
var CFBundlesForURLStrings = { },
|
||||
CFBundlesForClasses = { },
|
||||
CFCacheBuster = new Date().getTime(),
|
||||
CFTotalBytesLoaded = 0,
|
||||
CPApplicationSizeInBytes = 0;
|
||||
|
||||
GLOBAL(CFBundle) = function(/*String*/ aPath)
|
||||
GLOBAL(CFBundle) = function(/*CFURL|String*/ aURL)
|
||||
{
|
||||
aPath = FILE.absolute(aPath);
|
||||
aURL = resolveURL(aURL).asDirectoryPathURL();
|
||||
|
||||
var existingBundle = CFBundlesForPaths[aPath];
|
||||
var URLString = aURL.absoluteString(),
|
||||
existingBundle = CFBundlesForURLStrings[URLString];
|
||||
|
||||
if (existingBundle)
|
||||
return existingBundle;
|
||||
|
||||
CFBundlesForPaths[aPath] = this;
|
||||
CFBundlesForURLStrings[URLString] = this;
|
||||
|
||||
this._bundleURL = aURL;
|
||||
this._resourcesDirectoryURL = new CFURL("Resources/", aURL);
|
||||
|
||||
this._path = aPath;
|
||||
this._name = FILE.basename(aPath);
|
||||
this._staticResource = NULL;
|
||||
|
||||
this._loadStatus = CFBundleUnloaded;
|
||||
@@ -63,18 +65,18 @@ CFBundle.environments = function()
|
||||
return ENVIRONMENTS;
|
||||
}
|
||||
|
||||
CFBundle.bundleContainingPath = function(/*String*/ aPath)
|
||||
CFBundle.bundleContainingURL = function(/*CFURL*/ aURL)
|
||||
{
|
||||
aPath = FILE.absolute(aPath);
|
||||
aURL = new CFURL(".", resolveURL(aURL));
|
||||
|
||||
while (aPath !== "/")
|
||||
while (aURL.path() !== "/")
|
||||
{
|
||||
var bundle = CFBundlesForPaths[aPath];
|
||||
var bundle = CFBundlesForURLStrings[aURL.absoluteString()];
|
||||
|
||||
if (bundle)
|
||||
return bundle;
|
||||
|
||||
aPath = FILE.dirname(aPath);
|
||||
aURL = new CFURL("..", aURL);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
@@ -82,7 +84,7 @@ CFBundle.bundleContainingPath = function(/*String*/ aPath)
|
||||
|
||||
CFBundle.mainBundle = function()
|
||||
{
|
||||
return new CFBundle(FILE.cwd());
|
||||
return new CFBundle(mainBundleURL);
|
||||
}
|
||||
|
||||
function addClassToBundle(aClass, aBundle)
|
||||
@@ -96,9 +98,50 @@ CFBundle.bundleForClass = function(/*Class*/ aClass)
|
||||
return CFBundlesForClasses[aClass.name] || CFBundle.mainBundle();
|
||||
}
|
||||
|
||||
CFBundle.prototype.path = function()
|
||||
CFBundle.prototype.bundleURL = function()
|
||||
{
|
||||
return this._path;
|
||||
return this._bundleURL;
|
||||
}
|
||||
|
||||
CFBundle.prototype.resourcesDirectoryURL = function()
|
||||
{
|
||||
return this._resourcesDirectoryURL;
|
||||
}
|
||||
|
||||
CFBundle.prototype.resourceURL = function(/*String*/ aResourceName, /*String*/ aType, /*String*/ aSubDirectory)
|
||||
{
|
||||
if (aType)
|
||||
aResourceName = aResourceName + "." + aType;
|
||||
|
||||
if (aSubDirectory)
|
||||
aResourceName = aSubDirectory + "/" + aResourceName;
|
||||
|
||||
var resourceURL = (new CFURL(aResourceName, this.resourcesDirectoryURL())).mappedURL();
|
||||
|
||||
return resourceURL.absoluteURL();
|
||||
}
|
||||
|
||||
CFBundle.prototype.mostEligibleEnvironmentURL = function()
|
||||
{
|
||||
if (this._mostEligibleEnvironmentURL === undefined)
|
||||
this._mostEligibleEnvironmentURL = new CFURL(this.mostEligibleEnvironment() + ".environment/", this.bundleURL());
|
||||
|
||||
return this._mostEligibleEnvironmentURL;
|
||||
}
|
||||
|
||||
CFBundle.prototype.executableURL = function()
|
||||
{
|
||||
if (this._executableURL === undefined)
|
||||
{
|
||||
var executableSubPath = this.valueForInfoDictionaryKey("CPBundleExecutable");
|
||||
|
||||
if (!executableSubPath)
|
||||
this._executableURL = NULL;
|
||||
else
|
||||
this._executableURL = new CFURL(executableSubPath, this.mostEligibleEnvironmentURL());
|
||||
}
|
||||
|
||||
return this._executableURL;
|
||||
}
|
||||
|
||||
CFBundle.prototype.infoDictionary = function()
|
||||
@@ -106,37 +149,11 @@ CFBundle.prototype.infoDictionary = function()
|
||||
return this._infoDictionary;
|
||||
}
|
||||
|
||||
CFBundle.prototype.valueForInfoDictionary = function(/*String*/ aKey)
|
||||
CFBundle.prototype.valueForInfoDictionaryKey = function(/*String*/ aKey)
|
||||
{
|
||||
return this._infoDictionary.valueForKey(aKey);
|
||||
}
|
||||
|
||||
CFBundle.prototype.resourcesPath = function()
|
||||
{
|
||||
return FILE.join(this.path(), "Resources");
|
||||
}
|
||||
|
||||
CFBundle.prototype.pathForResource = function(/*String*/ aPath)
|
||||
{
|
||||
var mappedPath = this._URIMap[FILE.join("Resources", aPath)];
|
||||
|
||||
if (mappedPath)
|
||||
return mappedPath;
|
||||
|
||||
// If not, return the trivial path.
|
||||
return FILE.join(this.resourcesPath(), aPath);
|
||||
}
|
||||
|
||||
CFBundle.prototype.executablePath = function()
|
||||
{
|
||||
var executableSubPath = this._infoDictionary.valueForKey("CPBundleExecutable");
|
||||
|
||||
if (executableSubPath)
|
||||
return FILE.join(this.path(), this.mostEligibleEnvironment() + ".environment", executableSubPath);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CFBundle.prototype.hasSpritedImages = function()
|
||||
{
|
||||
var environments = this._infoDictionary.valueForKey("CPBundleEnvironmentsWithImageSprites") || [],
|
||||
@@ -192,23 +209,19 @@ CFBundle.prototype.load = function(/*BOOL*/ shouldExecute)
|
||||
|
||||
var self = this;
|
||||
|
||||
rootResource.resolveSubPath(FILE.dirname(self.path()), YES, function(aStaticResource)
|
||||
|
||||
var parentURL = new CFURL("..", this.bundleURL());
|
||||
|
||||
//???
|
||||
if (parentURL.absoluteString() === this.bundleURL().absoluteString())
|
||||
parentURL = parentURL.schemeAndAuthority();
|
||||
|
||||
StaticResource.resolveResourceAtURL(parentURL, YES, function(aStaticResource)
|
||||
{
|
||||
var path = self.path();
|
||||
var resourceName = self.bundleURL().absoluteURL().lastPathComponent();
|
||||
|
||||
// If this bundle exists at the root path, no need to create a node.
|
||||
if (path === "/")
|
||||
self._staticResource = rootResource;
|
||||
|
||||
else
|
||||
{
|
||||
var name = FILE.basename(path);
|
||||
|
||||
self._staticResource = aStaticResource._children[name];
|
||||
|
||||
if (!self._staticResource)
|
||||
self._staticResource = new StaticResource(name, aStaticResource, YES, NO);
|
||||
}
|
||||
self._staticResource = aStaticResource._children[resourceName] ||
|
||||
new StaticResource(resourceName, aStaticResource, YES, NO);
|
||||
|
||||
function onsuccess(/*Event*/ anEvent)
|
||||
{
|
||||
@@ -222,8 +235,8 @@ CFBundle.prototype.load = function(/*BOOL*/ shouldExecute)
|
||||
return;
|
||||
}
|
||||
|
||||
if (self === CFBundle.mainBundle() && self.valueForInfoDictionary("CPApplicationSize"))
|
||||
CPApplicationSizeInBytes = self.valueForInfoDictionary("CPApplicationSize").valueForKey("executable") || 0;
|
||||
if (self === CFBundle.mainBundle() && self.valueForInfoDictionaryKey("CPApplicationSize"))
|
||||
CPApplicationSizeInBytes = self.valueForInfoDictionaryKey("CPApplicationSize").valueForKey("executable") || 0;
|
||||
|
||||
loadExecutableAndResources(self, shouldExecute);
|
||||
}
|
||||
@@ -232,10 +245,10 @@ CFBundle.prototype.load = function(/*BOOL*/ shouldExecute)
|
||||
{
|
||||
self._loadStatus = CFBundleUnloaded;
|
||||
|
||||
finishBundleLoadingWithError(self, new Error("Could not load bundle at \"" + path + "\""));
|
||||
finishBundleLoadingWithError(self, new Error("Could not load bundle at \"" + self.bundleURL() + "\""));
|
||||
}
|
||||
|
||||
new FileRequest(FILE.join(path, "Info.plist"), onsuccess, onfailure);
|
||||
new FileRequest(new CFURL("Info.plist", self.bundleURL()), onsuccess, onfailure);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -279,7 +292,7 @@ function loadExecutableAndResources(/*Bundle*/ aBundle, /*BOOL*/ shouldExecute)
|
||||
|
||||
function success()
|
||||
{
|
||||
if ((typeof CPApp === "undefined" || !CPApp || !CPApp._finishedLaunching) &&
|
||||
if ((typeof CPApp === "undefined" || !CPApp || !CPApp._finishedLaunching) &&
|
||||
typeof OBJJ_PROGRESS_CALLBACK === "function" && CPApplicationSizeInBytes)
|
||||
{
|
||||
OBJJ_PROGRESS_CALLBACK(MAX(MIN(1.0, CFTotalBytesLoaded / CPApplicationSizeInBytes), 0.0), CPApplicationSizeInBytes, aBundle.path())
|
||||
@@ -312,17 +325,19 @@ function loadExecutableAndResources(/*Bundle*/ aBundle, /*BOOL*/ shouldExecute)
|
||||
|
||||
function loadExecutableForBundle(/*Bundle*/ aBundle, success, failure)
|
||||
{
|
||||
if (!aBundle.executablePath())
|
||||
var executableURL = aBundle.executableURL();
|
||||
|
||||
if (!executableURL)
|
||||
return;
|
||||
|
||||
aBundle._loadStatus |= CFBundleLoadingExecutable;
|
||||
|
||||
new FileRequest(aBundle.executablePath(), function(/*Event*/ anEvent)
|
||||
new FileRequest(executableURL, function(/*Event*/ anEvent)
|
||||
{
|
||||
try
|
||||
{
|
||||
CFTotalBytesLoaded += anEvent.request.responseText().length;
|
||||
decompileStaticFile(aBundle, anEvent.request.responseText(), aBundle.executablePath());
|
||||
decompileStaticFile(aBundle, anEvent.request.responseText(), executableURL);
|
||||
aBundle._loadStatus &= ~CFBundleLoadingExecutable;
|
||||
success();
|
||||
}
|
||||
@@ -333,6 +348,23 @@ function loadExecutableForBundle(/*Bundle*/ aBundle, success, failure)
|
||||
}, failure);
|
||||
}
|
||||
|
||||
function spritedImagesTestURLStringForBundle(/*Bundle*/ aBundle)
|
||||
{
|
||||
return "mhtml:" + new CFURL("MHTMLTest.txt", aBundle.mostEligibleEnvironmentURL());
|
||||
}
|
||||
|
||||
function spritedImagesURLForBundle(/*Bundle*/ aBundle)
|
||||
{
|
||||
if (CFBundleSupportedSpriteType === CFBundleDataURLSpriteType)
|
||||
return new CFURL("dataURLs.txt", aBundle.mostEligibleEnvironmentURL());
|
||||
|
||||
if (CFBundleSupportedSpriteType === CFBundleMHTMLSpriteType ||
|
||||
CFBundleSupportedSpriteType === CFBundleMHTMLUncachedSpriteType)
|
||||
return new CFURL("MHTMLPaths.txt", aBundle.mostEligibleEnvironmentURL());
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
function loadSpritedImagesForBundle(/*Bundle*/ aBundle, success, failure)
|
||||
{
|
||||
if (!aBundle.hasSpritedImages())
|
||||
@@ -341,25 +373,25 @@ function loadSpritedImagesForBundle(/*Bundle*/ aBundle, success, failure)
|
||||
aBundle._loadStatus |= CFBundleLoadingSpritedImages;
|
||||
|
||||
if (!CFBundleHasTestedSpriteSupport())
|
||||
return CFBundleTestSpriteSupport(spritedImagesTestPathForBundle(aBundle), function()
|
||||
return CFBundleTestSpriteSupport(spritedImagesTestURLStringForBundle(aBundle), function()
|
||||
{
|
||||
loadSpritedImagesForBundle(aBundle, success, failure);
|
||||
});
|
||||
|
||||
var spritedImagesPath = spritedImagesPathForBundle(aBundle);
|
||||
var spritedImagesURL = spritedImagesURLForBundle(aBundle);
|
||||
|
||||
if (!spritedImagesPath)
|
||||
if (!spritedImagesURL)
|
||||
{
|
||||
aBundle._loadStatus &= ~CFBundleLoadingSpritedImages;
|
||||
return success();
|
||||
}
|
||||
|
||||
new FileRequest(spritedImagesPath, function(/*Event*/ anEvent)
|
||||
new FileRequest(spritedImagesURL, function(/*Event*/ anEvent)
|
||||
{
|
||||
try
|
||||
{
|
||||
CFTotalBytesLoaded += anEvent.request.responseText().length;
|
||||
decompileStaticFile(aBundle, anEvent.request.responseText(), spritedImagesPath);
|
||||
decompileStaticFile(aBundle, anEvent.request.responseText(), spritedImagesURL);
|
||||
aBundle._loadStatus &= ~CFBundleLoadingSpritedImages;
|
||||
success();
|
||||
}
|
||||
@@ -395,7 +427,7 @@ function CFBundleTestSpriteSupport(/*String*/ MHTMLPath, /*Function*/ aCallback)
|
||||
CFBundleSpriteSupportListeners.push(function()
|
||||
{
|
||||
var size = 0,
|
||||
sizeDictionary = CFBundle.mainBundle().valueForInfoDictionary("CPApplicationSize");
|
||||
sizeDictionary = CFBundle.mainBundle().valueForInfoDictionaryKey("CPApplicationSize");
|
||||
|
||||
if (!sizeDictionary)
|
||||
return;
|
||||
@@ -463,45 +495,9 @@ function CFBundleTestSpriteTypes(/*Array*/ spriteTypes)
|
||||
image.src = spriteTypes[1];
|
||||
}
|
||||
|
||||
function mhtmlBasePath()
|
||||
{
|
||||
#ifdef BROWSER
|
||||
//FIXME: URL stuff is kind of broken
|
||||
return window.location.protocol + "//" + window.location.hostname + (window.location.port ? (":" + window.location.port) : "");
|
||||
#else
|
||||
return "";
|
||||
#endif
|
||||
}
|
||||
|
||||
function spritedImagesTestPathForBundle(/*Bundle*/ aBundle)
|
||||
{
|
||||
return "mhtml:" + mhtmlBasePath() + FILE.join(aBundle.path(), aBundle.mostEligibleEnvironment() + ".environment", "MHTMLTest.txt");
|
||||
}
|
||||
|
||||
function spritedImagesPathForBundle(/*Bundle*/ aBundle)
|
||||
{
|
||||
if (CFBundleSupportedSpriteType === CFBundleDataURLSpriteType)
|
||||
return FILE.join(aBundle.path(), aBundle.mostEligibleEnvironment() + ".environment", "dataURLs.txt");
|
||||
|
||||
if (CFBundleSupportedSpriteType === CFBundleMHTMLSpriteType || CFBundleSupportedSpriteType === CFBundleMHTMLUncachedSpriteType)
|
||||
return mhtmlBasePath() + FILE.join(aBundle.path(), aBundle.mostEligibleEnvironment() + ".environment", "MHTMLPaths.txt");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CFBundle.dataContentsAtPath = function(/*String*/ aPath)
|
||||
{
|
||||
var data = new CFMutableData();
|
||||
|
||||
data.setRawString(rootResource.nodeAtSubPath(aPath).contents());
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
function executeBundle(/*Bundle*/ aBundle, /*Function*/ aCallback)
|
||||
{
|
||||
var staticResources = [aBundle._staticResource],
|
||||
resourcesPath = aBundle.resourcesPath();
|
||||
var staticResources = [aBundle._staticResource];
|
||||
|
||||
function executeStaticResources(index)
|
||||
{
|
||||
@@ -514,7 +510,7 @@ function executeBundle(/*Bundle*/ aBundle, /*Function*/ aCallback)
|
||||
|
||||
if (staticResource.isFile())
|
||||
{
|
||||
var executable = new FileExecutable(staticResource.path());
|
||||
var executable = new FileExecutable(staticResource.URL());
|
||||
|
||||
if (executable.hasLoadedFileDependencies())
|
||||
executable.execute();
|
||||
@@ -532,7 +528,7 @@ function executeBundle(/*Bundle*/ aBundle, /*Function*/ aCallback)
|
||||
else //if (staticResource.isDirectory())
|
||||
{
|
||||
// We don't want to execute resources.
|
||||
if (staticResource.path() === aBundle.resourcesPath())
|
||||
if (staticResource.URL().absoluteString() === aBundle.resourcesDirectoryURL().absoluteString())
|
||||
continue;
|
||||
|
||||
var children = staticResource.children();
|
||||
@@ -562,13 +558,13 @@ function decompileStaticFile(/*Bundle*/ aBundle, /*String*/ aString, /*String*/
|
||||
var stream = new MarkedStream(aString);
|
||||
|
||||
if (stream.magicNumber() !== STATIC_MAGIC_NUMBER)
|
||||
throw new Error("Could not read static file: "+aPath);
|
||||
throw new Error("Could not read static file: " + aPath);
|
||||
|
||||
if (stream.version() !== "1.0")
|
||||
throw new Error("Could not read static file: "+aPath);
|
||||
throw new Error("Could not read static file: " + aPath);
|
||||
|
||||
var marker,
|
||||
bundlePath = aBundle.path(),
|
||||
bundleURL = aBundle.bundleURL(),
|
||||
file = NULL;
|
||||
|
||||
while (marker = stream.getMarker())
|
||||
@@ -577,35 +573,44 @@ function decompileStaticFile(/*Bundle*/ aBundle, /*String*/ aString, /*String*/
|
||||
|
||||
if (marker === MARKER_PATH)
|
||||
{
|
||||
var absolutePath = FILE.join(bundlePath, text),
|
||||
parent = rootResource.nodeAtSubPath(FILE.dirname(absolutePath), YES);
|
||||
var fileURL = new CFURL(text, bundleURL),
|
||||
parent = StaticResource.resourceAtURL(new CFURL(".", fileURL), YES);
|
||||
|
||||
file = new StaticResource(FILE.basename(absolutePath), parent, NO, YES);
|
||||
file = new StaticResource(fileURL.lastPathComponent(), parent, NO, YES);
|
||||
}
|
||||
|
||||
else if (marker === MARKER_URI)
|
||||
{
|
||||
var URI = stream.getString();
|
||||
var URL = new CFURL(text, bundleURL),
|
||||
mappedURL,
|
||||
mappedURLString = stream.getString();
|
||||
|
||||
if (URI.toLowerCase().indexOf("mhtml:") === 0)
|
||||
if (mappedURLString.toLowerCase().indexOf("mhtml:") === 0)
|
||||
{
|
||||
URI = "mhtml:" + mhtmlBasePath() + FILE.join(bundlePath, URI.substr("mhtml:".length));
|
||||
mappedURLString = "mhtml:" + new CFURL(URLString.substr("mhtml:".length), bundleURL);
|
||||
/*
|
||||
URLString = "mhtml:" + URL;
|
||||
|
||||
if (CFBundleSupportedSpriteType === CFBundleMHTMLUncachedSpriteType)
|
||||
{
|
||||
var exclamationIndex = URI.indexOf("!"),
|
||||
firstPart = URI.substring(0, exclamationIndex),
|
||||
lastPart = URI.substring(exclamationIndex);
|
||||
var exclamationIndex = URLString.indexOf("!"),
|
||||
firstPart = URLString.substring(0, exclamationIndex),
|
||||
lastPart = URLString.substring(exclamationIndex);
|
||||
|
||||
URI = firstPart + "?" + CFCacheBuster + lastPart;
|
||||
URLString = firstPart + "?" + CFCacheBuster + lastPart;
|
||||
}
|
||||
|
||||
mappedURL = new CFURL(URLString);*/
|
||||
}
|
||||
aBundle._URIMap[text] = URI;
|
||||
else
|
||||
mappedURL = new CFURL(mappedURLString);
|
||||
|
||||
CFURL.setMappedURLForURL(URL, mappedURL);
|
||||
|
||||
// The unresolved directories must not be bundles.
|
||||
var parent = rootResource.nodeAtSubPath(FILE.join(bundlePath, FILE.dirname(text)), YES);
|
||||
var parent = StaticResource.resourceAtURL(new CFURL(".", URL), YES);
|
||||
|
||||
new StaticResource(FILE.basename(text), parent, NO, YES);
|
||||
new StaticResource(URL.lastPathComponent(), parent, NO, YES);
|
||||
}
|
||||
|
||||
else if (marker === MARKER_TEXT)
|
||||
@@ -629,3 +634,15 @@ CFBundle.prototype.onerror = function(/*Event*/ anEvent)
|
||||
{
|
||||
throw anEvent.error;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
CFBundle.prototype.path = function()
|
||||
{
|
||||
return this._bundleURL.absoluteString();
|
||||
}
|
||||
|
||||
CFBundle.prototype.pathForResource = function(aResource)
|
||||
{
|
||||
return this.resourceURL(aResource).absoluteString();
|
||||
}
|
||||
|
||||
@@ -252,7 +252,7 @@ function determineAndDispatchHTTPRequestEvents(/*CFHTTPRequest*/ aRequest)
|
||||
}
|
||||
}
|
||||
|
||||
function FileRequest(/*String*/ aFilePath, onsuccess, onfailure)
|
||||
function FileRequest(/*CFURL*/ aURL, onsuccess, onfailure)
|
||||
{
|
||||
#ifdef BROWSER
|
||||
var request = new CFHTTPRequest();
|
||||
@@ -260,16 +260,19 @@ function FileRequest(/*String*/ aFilePath, onsuccess, onfailure)
|
||||
request.onsuccess = Asynchronous(onsuccess);
|
||||
request.onfailure = Asynchronous(onfailure);
|
||||
|
||||
if (FILE.extension(aFilePath) === ".plist")
|
||||
if (aURL.pathExtension() === "plist")
|
||||
request.overrideMimeType("text/xml");
|
||||
|
||||
request.open("GET", aFilePath, YES);
|
||||
request.open("GET", aURL.absoluteString(), YES);
|
||||
request.send("");
|
||||
#else
|
||||
if (!FILE.exists(aFilePath))
|
||||
var FILE = require("file"),
|
||||
filePath = aURL.absoluteURL().path();
|
||||
|
||||
if (!FILE.exists(filePath))
|
||||
return onfailure();
|
||||
|
||||
this._responseText = FILE.read(aFilePath, { charset:"UTF-8" });
|
||||
this._responseText = FILE.read(filePath, { charset:"UTF-8" });
|
||||
|
||||
onsuccess({ type:"success", request:this });
|
||||
#endif
|
||||
|
||||
+133
-15
@@ -1,24 +1,64 @@
|
||||
// Based on the regex in RFC2396 Appendix B.
|
||||
var URI_RE = /^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/;
|
||||
|
||||
GLOBAL(CFURL) = function(/*CFURL|String*/ aURLOrString, /*CFURL*/ aBaseURL)
|
||||
GLOBAL(CFURL) = function(/*CFURL|String*/ aURL, /*CFURL*/ aBaseURL)
|
||||
{
|
||||
if (aURLOrString instanceof CFURL)
|
||||
return new CFURL(aURLOrString.string(), aBaseURL);
|
||||
if (aURL instanceof CFURL)
|
||||
if (!aBaseURL)
|
||||
return aURL
|
||||
else
|
||||
{
|
||||
var existingBaseURL = aURL.baseURL();
|
||||
|
||||
this._string = aURLOrString;
|
||||
if (existingBaseURL)
|
||||
aBaseURL = new CFURL(existingBaseURL, aBaseURL);
|
||||
|
||||
var result = (aURLOrString || "").match(URI_RE);
|
||||
return new CFURL(aURL.string(), aBaseURL);
|
||||
}
|
||||
|
||||
this._UID = objj_generateObjectUID();
|
||||
this._string = aURL;
|
||||
|
||||
var result = (aURL || "").match(URI_RE);
|
||||
|
||||
this._baseURL = aBaseURL;
|
||||
this._resourcePropertiesForKeys = new CFMutableDictionary();
|
||||
|
||||
this._scheme = result[2] || NULL;
|
||||
this._authority = result[4] || NULL;
|
||||
this._path = result[5] || NULL;
|
||||
this._scheme = result[2];
|
||||
this._authority = result[4];
|
||||
this._path = result[5] || "";
|
||||
this._queryString = result[7] || NULL;
|
||||
this._fragment = result[9] || NULL;
|
||||
}
|
||||
|
||||
var URLMap = { };
|
||||
|
||||
CFURL.prototype.mappedURL = function()
|
||||
{
|
||||
return URLMap[this.absoluteString()] || this;
|
||||
}
|
||||
|
||||
CFURL.setMappedURLForURL = function(/*CFURL*/ fromURL, /*CFURL*/ toURL)
|
||||
{
|
||||
URLMap[fromURL.absoluteString()] = toURL;
|
||||
}
|
||||
|
||||
CFURL.prototype.schemeAndAuthority = function()
|
||||
{
|
||||
var string = "",
|
||||
scheme = this.scheme();
|
||||
|
||||
if (scheme)
|
||||
string += scheme + ":";
|
||||
|
||||
var authority = this.authority();
|
||||
|
||||
if (authority)
|
||||
string += "//" + authority;
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
CFURL.prototype.absoluteString = function()
|
||||
{
|
||||
return this.absoluteURL().string();
|
||||
@@ -35,7 +75,7 @@ CFURL.prototype.absoluteURL = function()
|
||||
{
|
||||
var baseURL = this._baseURL;
|
||||
|
||||
this._absoluteURL = baseURL ? resolve(baseURL.string(), this.string()) : this;
|
||||
this._absoluteURL = baseURL ? new CFURL(resolve(baseURL.absoluteString(), this.string())) : this;
|
||||
}
|
||||
|
||||
return this._absoluteURL;
|
||||
@@ -48,12 +88,22 @@ CFURL.prototype.string = function()
|
||||
|
||||
CFURL.prototype.authority = function()
|
||||
{
|
||||
return this._authority;
|
||||
var authority = this._authority;
|
||||
|
||||
if (authority === undefined)
|
||||
{
|
||||
var baseURL = this.baseURL();
|
||||
|
||||
authority = baseURL && baseURL.authority() || NULL;
|
||||
this._authority = authority;
|
||||
}
|
||||
|
||||
return authority;
|
||||
}
|
||||
|
||||
CFURL.prototype.hasDirectoryPath = function()
|
||||
{
|
||||
var path = this._path;
|
||||
var path = this.path();
|
||||
|
||||
if (!path)
|
||||
return NO;
|
||||
@@ -93,6 +143,39 @@ CFURL.prototype.path = function()
|
||||
return this._path;
|
||||
}
|
||||
|
||||
CFURL.prototype.pathComponents = function()
|
||||
{
|
||||
if (!this._pathComponents)
|
||||
{
|
||||
var path = this.path();
|
||||
|
||||
if (!path)
|
||||
this._pathComponents = [];
|
||||
else
|
||||
{
|
||||
var components = path.split("/"),
|
||||
result = [],
|
||||
index = 0,
|
||||
count = components.length;
|
||||
|
||||
for (; index < count; ++index)
|
||||
{
|
||||
var component = components[index];
|
||||
|
||||
if (component)
|
||||
result.push(component);
|
||||
|
||||
else if (index === 0)
|
||||
result.push("/");
|
||||
}
|
||||
|
||||
this._pathComponents = result;
|
||||
}
|
||||
}
|
||||
|
||||
return this._pathComponents;
|
||||
}
|
||||
|
||||
CFURL.prototype.pathExtension = function()
|
||||
{
|
||||
var lastPathComponent = this.lastPathComponent();
|
||||
@@ -114,7 +197,17 @@ CFURL.prototype.queryString = function()
|
||||
|
||||
CFURL.prototype.scheme = function()
|
||||
{
|
||||
return this._scheme;
|
||||
var scheme = this._scheme;
|
||||
|
||||
if (scheme === undefined)
|
||||
{
|
||||
var baseURL = this.baseURL();
|
||||
|
||||
scheme = baseURL && baseURL.scheme() || NULL;
|
||||
this._scheme = scheme;
|
||||
}
|
||||
|
||||
return scheme;
|
||||
}
|
||||
|
||||
CFURL.prototype.baseURL = function()
|
||||
@@ -122,7 +215,32 @@ CFURL.prototype.baseURL = function()
|
||||
return this._baseURL;
|
||||
}
|
||||
|
||||
CFURL.prototype.asDirectoryPathURL = function()
|
||||
{
|
||||
if (this.hasDirectoryPath())
|
||||
return this;
|
||||
|
||||
return new CFURL(this.lastPathComponent() + "/", this);
|
||||
}
|
||||
|
||||
CFURL.prototype.resourcePropertyForKey = function(/*String*/ aKey)
|
||||
{
|
||||
return this._resourcePropertiesForKeys.objectForKey(aKey);
|
||||
}
|
||||
|
||||
CFURL.prototype.setResourcePropertyForKey = function(/*String*/ aKey, /*id*/ aValue)
|
||||
{
|
||||
this._resourcePropertiesForKeys.setObjectForKey(aKey, aValue);
|
||||
}
|
||||
|
||||
CFURL.prototype.staticResourceData = function()
|
||||
{
|
||||
var data = new CFMutableData();
|
||||
|
||||
data.setRawString(StaticResource.resourceAtURL(this).contents());
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
// from Chiron's HTTP module:
|
||||
|
||||
@@ -335,7 +453,7 @@ var resolveObject = function (source, relative) {
|
||||
) {
|
||||
source = relative;
|
||||
} else {
|
||||
if (relative.root) {
|
||||
if (relative.root || relative.protocol) {
|
||||
source.directories = relative.directories;
|
||||
} else {
|
||||
|
||||
@@ -363,9 +481,9 @@ var resolveObject = function (source, relative) {
|
||||
}
|
||||
}
|
||||
|
||||
if (relative.root)
|
||||
if (relative.root || relative.protocol)
|
||||
source.root = relative.root;
|
||||
if (relative.protcol)
|
||||
if (relative.protocol)
|
||||
source.protocol = relative.protocol;
|
||||
if (!(!relative.path && relative.anchor))
|
||||
source.file = relative.file;
|
||||
|
||||
@@ -155,8 +155,8 @@ exports.objj_eval = function(/*String*/ aString)
|
||||
var code = executable._code;
|
||||
|
||||
// Not clear why these should be global, varing them doesn't seem to take effect with evaluateString.
|
||||
global.objj_executeFile = Executable.fileExecuterForPath(FILE.cwd());
|
||||
global.objj_importFile = Executable.fileImporterForPath(FILE.cwd());
|
||||
global.objj_executeFile = Executable.fileExecuterForURL(FILE.cwd());
|
||||
global.objj_importFile = Executable.fileImporterForURL(FILE.cwd());
|
||||
|
||||
if (typeof system !== "undefined" && system.engine === "rhino")
|
||||
return Packages.org.mozilla.javascript.Context.getCurrentContext().evaluateString(global, code, "objj_eval", 0, NULL);
|
||||
@@ -173,7 +173,7 @@ exports.make_narwhal_factory = function(path)
|
||||
{
|
||||
Executable.setCommonJSArguments(require, exports, module, system, print, window);
|
||||
|
||||
Executable.fileImporterForPath(FILE.dirname(path))(path, function()
|
||||
Executable.fileImporterForURL(FILE.dirname(path))(path, YES, function()
|
||||
{
|
||||
print("all done");
|
||||
});
|
||||
|
||||
@@ -30,7 +30,7 @@ EventDispatcher.prototype.addEventListener = function(/*String*/ anEventName, /*
|
||||
{
|
||||
var eventListenersForEventNames = this._eventListenersForEventNames;
|
||||
|
||||
if (!hasOwnProperty.call(this._eventListenersForEventNames, anEventName))
|
||||
if (!hasOwnProperty.call(eventListenersForEventNames, anEventName))
|
||||
{
|
||||
var eventListenersForEventName = [];
|
||||
eventListenersForEventNames[anEventName] = eventListenersForEventName;
|
||||
@@ -54,7 +54,7 @@ EventDispatcher.prototype.removeEventListener = function(/*String*/ anEventName,
|
||||
if (!hasOwnProperty.call(eventListenersForEventNames, anEventName))
|
||||
return;
|
||||
|
||||
var eventListenersForEventName = eventListenersForEventNames[anEventName].
|
||||
var eventListenersForEventName = eventListenersForEventNames[anEventName],
|
||||
index = eventListenersForEventName.length;
|
||||
|
||||
while (index--)
|
||||
|
||||
+49
-57
@@ -22,7 +22,9 @@
|
||||
|
||||
var ExecutableUnloadedFileDependencies = 0,
|
||||
ExecutableLoadingFileDependencies = 1,
|
||||
ExecutableLoadedFileDependencies = 2;
|
||||
ExecutableLoadedFileDependencies = 2,
|
||||
AnonymousExecutableCount = 0;
|
||||
|
||||
|
||||
function Executable(/*String*/ aCode, /*Array*/ fileDependencies, /*CFURL*/ aURL, /*Function*/ aFunction)
|
||||
{
|
||||
@@ -31,7 +33,7 @@ function Executable(/*String*/ aCode, /*Array*/ fileDependencies, /*CFURL*/ aURL
|
||||
|
||||
this._code = aCode;
|
||||
this._function = aFunction || NULL;
|
||||
this._URL = aURL || new CFURL("(Anonymous)", mainBundleURL);
|
||||
this._URL = resolveURL(aURL || new CFURL("(Anonymous" + (AnonymousExecutableCount++) + ")", mainBundleURL));
|
||||
|
||||
this._fileDependencies = fileDependencies;
|
||||
this._fileDependencyLoadStatus = ExecutableUnloadedFileDependencies;
|
||||
@@ -124,7 +126,7 @@ Executable.prototype.execute = function()
|
||||
#endif
|
||||
var oldContextBundle = CONTEXT_BUNDLE;
|
||||
|
||||
CONTEXT_BUNDLE = CFBundle.bundleContainingPath(this.path());
|
||||
CONTEXT_BUNDLE = CFBundle.bundleContainingURL(this.URL());
|
||||
|
||||
var result = this._function.apply(global, this.functionArguments());
|
||||
|
||||
@@ -197,7 +199,7 @@ Executable.prototype.loadFileDependencies = function()
|
||||
|
||||
this._fileDependencyLoadStatus = ExecutableLoadingFileDependencies;
|
||||
|
||||
var searchedPaths = [{ }, { }],
|
||||
var searchedURLStrings = [{ }, { }],
|
||||
fileExecutableSearches = new CFMutableDictionary(),
|
||||
incompleteFileExecutableSearches = new CFMutableDictionary(),
|
||||
loadingExecutables = { };
|
||||
@@ -215,11 +217,11 @@ Executable.prototype.loadFileDependencies = function()
|
||||
if (executable.hasLoadedFileDependencies())
|
||||
continue;
|
||||
|
||||
var executablePath = executable.path();
|
||||
var executableURLString = executable.URL().absoluteString();
|
||||
|
||||
loadingExecutables[executablePath] = executable;
|
||||
loadingExecutables[executableURLString] = executable;
|
||||
|
||||
var cwd = FILE.dirname(executablePath),
|
||||
var referenceURL = new CFURL(".", executable.URL()),
|
||||
fileDependencies = executable.fileDependencies(),
|
||||
fileDependencyIndex = 0,
|
||||
fileDependencyCount = fileDependencies.length;
|
||||
@@ -228,14 +230,19 @@ Executable.prototype.loadFileDependencies = function()
|
||||
{
|
||||
var fileDependency = fileDependencies[fileDependencyIndex],
|
||||
isLocal = fileDependency.isLocal(),
|
||||
path = importablePath(fileDependency.path(), isLocal, cwd);
|
||||
URL = fileDependency.URL();
|
||||
|
||||
if (searchedPaths[isLocal ? 1 : 0][path])
|
||||
if (isLocal)
|
||||
URL = new CFURL(URL, referenceURL);
|
||||
|
||||
var URLString = URL.absoluteString();
|
||||
|
||||
if (searchedURLStrings[isLocal ? 1 : 0][URLString])
|
||||
continue;
|
||||
|
||||
searchedPaths[isLocal ? 1 : 0][path] = YES;
|
||||
searchedURLStrings[isLocal ? 1 : 0][URLString] = YES;
|
||||
|
||||
var fileExecutableSearch = new FileExecutableSearch(path, isLocal),
|
||||
var fileExecutableSearch = new FileExecutableSearch(URL, isLocal),
|
||||
fileExecutableSearchUID = fileExecutableSearch.UID();
|
||||
|
||||
if (fileExecutableSearches.containsKey(fileExecutableSearchUID))
|
||||
@@ -278,14 +285,14 @@ Executable.prototype.loadFileDependencies = function()
|
||||
CPLog("DEPENDENCY: Ended");
|
||||
#endif
|
||||
|
||||
for (var path in loadingExecutables)
|
||||
if (hasOwnProperty.call(loadingExecutables, path))
|
||||
loadingExecutables[path]._fileDependencyLoadStatus = ExecutableLoadedFileDependencies;
|
||||
for (var URLString in loadingExecutables)
|
||||
if (hasOwnProperty.call(loadingExecutables, URLString))
|
||||
loadingExecutables[URLString]._fileDependencyLoadStatus = ExecutableLoadedFileDependencies;
|
||||
|
||||
for (var path in loadingExecutables)
|
||||
if (hasOwnProperty.call(loadingExecutables, path))
|
||||
for (var URLString in loadingExecutables)
|
||||
if (hasOwnProperty.call(loadingExecutables, URLString))
|
||||
{
|
||||
var executable = loadingExecutables[path];
|
||||
var executable = loadingExecutables[URLString];
|
||||
|
||||
executable._eventDispatcher.dispatchEvent(
|
||||
{
|
||||
@@ -308,81 +315,67 @@ Executable.prototype.removeEventListener = function(/*String*/ anEventName, /*Fu
|
||||
this._eventDispatcher.removeEventListener(anEventName, aListener);
|
||||
}
|
||||
|
||||
function importablePath(/*String*/ aPath, /*BOOL*/ isLocal, /*String*/ aCWD)
|
||||
{
|
||||
aPath = FILE.normal(aPath);
|
||||
|
||||
if (FILE.isAbsolute(aPath))
|
||||
return aPath;
|
||||
|
||||
if (isLocal)
|
||||
aPath = FILE.normal(FILE.join(aCWD, aPath));
|
||||
|
||||
return aPath;
|
||||
}
|
||||
|
||||
Executable.prototype.fileImporter = function()
|
||||
{
|
||||
return Executable.fileImporterForPath(FILE.dirname(this.path()));
|
||||
return Executable.fileImporterForURL(new CFURL(".", this.URL()));
|
||||
}
|
||||
|
||||
Executable.prototype.fileExecuter = function()
|
||||
{
|
||||
return Executable.fileExecuterForPath(FILE.dirname(this.path()));
|
||||
return Executable.fileExecuterForURL(new CFURL(".", this.URL()));
|
||||
}
|
||||
|
||||
var cachedFileExecutersForPaths = { };
|
||||
var cachedFileExecutersForURLStrings = { };
|
||||
|
||||
Executable.fileExecuterForPath = function(/*String*/ referencePath)
|
||||
Executable.fileExecuterForURL = function(/*CFURL|String*/ aURL)
|
||||
{
|
||||
referencePath = FILE.normal(referencePath);
|
||||
var referenceURL = resolveURL(aURL),
|
||||
referenceURLString = referenceURL.absoluteString(),
|
||||
cachedFileExecuter = cachedFileExecutersForURLStrings[referenceURLString];
|
||||
|
||||
var fileExecuter = cachedFileExecutersForPaths[referencePath];
|
||||
|
||||
if (!fileExecuter)
|
||||
if (!cachedFileExecuter)
|
||||
{
|
||||
fileExecuter = function(/*String*/ aPath, /*BOOL*/ isLocal, /*BOOL*/ shouldForce)
|
||||
cachedFileExecuter = function(/*CFURL*/ aURL, /*BOOL*/ isQuoted, /*BOOL*/ shouldForce)
|
||||
{
|
||||
aPath = importablePath(aPath, isLocal, referencePath);
|
||||
aURL = new CFURL(aURL, isQuoted ? referenceURL : NULL);
|
||||
|
||||
var fileExecutableSearch = new FileExecutableSearch(aPath, isLocal),
|
||||
var fileExecutableSearch = new FileExecutableSearch(aURL, isQuoted),
|
||||
fileExecutable = fileExecutableSearch.result();
|
||||
|
||||
if (0 && !fileExecutable.hasLoadedFileDependencies())
|
||||
throw "No executable loaded for file at path " + aPath;
|
||||
if (!fileExecutable.hasLoadedFileDependencies())
|
||||
throw "No executable loaded for file at URL " + aURL;
|
||||
|
||||
fileExecutable.execute(shouldForce);
|
||||
}
|
||||
|
||||
cachedFileExecutersForPaths[referencePath] = fileExecuter;
|
||||
cachedFileExecutersForURLStrings[referenceURLString] = cachedFileExecuter;
|
||||
}
|
||||
|
||||
return fileExecuter;
|
||||
return cachedFileExecuter;
|
||||
}
|
||||
|
||||
var cachedImportersForPaths = { };
|
||||
var cachedImportersForURLStrings = { };
|
||||
|
||||
Executable.fileImporterForPath = function(/*String*/ referencePath)
|
||||
Executable.fileImporterForURL = function(/*CFURL*/ aURL)
|
||||
{
|
||||
referencePath = FILE.normal(referencePath);
|
||||
|
||||
var cachedImporter = cachedImportersForPaths[referencePath];
|
||||
var referenceURL = resolveURL(aURL),
|
||||
referenceURLString = referenceURL.absoluteString(),
|
||||
cachedImporter = cachedImportersForURLStrings[referenceURLString];
|
||||
|
||||
if (!cachedImporter)
|
||||
{
|
||||
cachedImporter = function(/*String*/ aPath, /*BOOL*/ isLocal, /*Function*/ aCallback)
|
||||
cachedImporter = function(/*CFURL*/ aURL, /*BOOL*/ isQuoted, /*Function*/ aCallback)
|
||||
{
|
||||
aPath = importablePath(aPath, isLocal, referencePath);
|
||||
aURL = new CFURL(aURL, isQuoted ? referenceURL : NULL);
|
||||
|
||||
var fileExecutableSearch = new FileExecutableSearch(aPath, isLocal);
|
||||
var fileExecutableSearch = new FileExecutableSearch(aURL, isQuoted);
|
||||
|
||||
function searchComplete(/*FileExecutableSearch*/ aFileExecutableSearch)
|
||||
{
|
||||
var fileExecutable = aFileExecutableSearch.result(),
|
||||
fileExecuter = Executable.fileExecuterForPath(referencePath),
|
||||
executeAndCallback = function ()
|
||||
{
|
||||
fileExecuter(aPath, isLocal);
|
||||
fileExecutable.execute();
|
||||
|
||||
if (aCallback)
|
||||
aCallback();
|
||||
@@ -406,9 +399,8 @@ Executable.fileImporterForPath = function(/*String*/ referencePath)
|
||||
});
|
||||
}
|
||||
|
||||
cachedImportersForPaths[referencePath] = cachedImporter;
|
||||
cachedImportersForURLStrings[referenceURLString] = cachedImporter;
|
||||
}
|
||||
|
||||
return cachedImporter;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,17 +20,17 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
function FileDependency(/*String*/ aPath, /*BOOL*/ isLocal)
|
||||
function FileDependency(/*CFURL*/ aURL, /*BOOL*/ isLocal)
|
||||
{
|
||||
this._path = FILE.normal(aPath);
|
||||
this._URL = aURL;
|
||||
this._isLocal = isLocal;
|
||||
}
|
||||
|
||||
exports.FileDependency = FileDependency;
|
||||
|
||||
FileDependency.prototype.path = function()
|
||||
FileDependency.prototype.URL = function()
|
||||
{
|
||||
return this._path;
|
||||
return this._URL;
|
||||
}
|
||||
|
||||
FileDependency.prototype.isLocal = function()
|
||||
@@ -40,11 +40,13 @@ FileDependency.prototype.isLocal = function()
|
||||
|
||||
FileDependency.prototype.toMarkedString = function()
|
||||
{
|
||||
var URLString = this.URL().absoluteString();
|
||||
|
||||
return (this.isLocal() ? MARKER_IMPORT_LOCAL : MARKER_IMPORT_STD) + ";" +
|
||||
this.path().length + ";" + this.path();
|
||||
URLString.length + ";" + URLString;
|
||||
}
|
||||
|
||||
FileDependency.prototype.toString = function()
|
||||
{
|
||||
return (this.isLocal() ? "LOCAL: " : "STD: ") + this.path();
|
||||
return (this.isLocal() ? "LOCAL: " : "STD: ") + this.URL();
|
||||
}
|
||||
|
||||
@@ -24,7 +24,8 @@ var FileExecutablesForURLStrings = { };
|
||||
|
||||
function FileExecutable(/*CFURL*/ aURL, /*Executable*/ anExecutable)
|
||||
{
|
||||
if (!aURL._path) aURL = new CFURL(aURL);
|
||||
aURL = resolveURL(aURL);
|
||||
|
||||
var URLString = aURL.absoluteString(),
|
||||
existingFileExecutable = FileExecutablesForURLStrings[URLString];
|
||||
|
||||
@@ -33,7 +34,7 @@ if (!aURL._path) aURL = new CFURL(aURL);
|
||||
|
||||
FileExecutablesForURLStrings[URLString] = this;
|
||||
|
||||
var fileContents = rootResource.nodeAtSubPath(aURL.path()).contents(),
|
||||
var fileContents = StaticResource.resourceAtURL(aURL).contents(),
|
||||
executable = NULL,
|
||||
extension = aURL.pathExtension();
|
||||
|
||||
@@ -111,10 +112,10 @@ function decompile(/*String*/ aString, /*CFURL*/ aURL)
|
||||
code += text;
|
||||
|
||||
else if (marker === MARKER_IMPORT_STD)
|
||||
dependencies.push(new FileDependency(text, NO));
|
||||
dependencies.push(new FileDependency(new CFURL(text), NO));
|
||||
|
||||
else if (marker === MARKER_IMPORT_LOCAL)
|
||||
dependencies.push(new FileDependency(text, YES));
|
||||
dependencies.push(new FileDependency(new CFURL(text), YES));
|
||||
}
|
||||
|
||||
return new Executable(code, dependencies, aURL);
|
||||
|
||||
@@ -22,22 +22,23 @@
|
||||
|
||||
var FileExecutableSearchesForPaths = [{ }, { }];
|
||||
|
||||
function FileExecutableSearch(/*String*/ aPath, /*BOOL*/ isLocal)
|
||||
function FileExecutableSearch(/*CFURL*/ aURL, /*BOOL*/ isQuoted)
|
||||
{
|
||||
if (!FILE.isAbsolute(aPath) && isLocal)
|
||||
throw "Local searches cannot be relative: " + aPath;
|
||||
|
||||
var existingSearch = FileExecutableSearchesForPaths[isLocal ? 1 : 0][aPath];
|
||||
// if (isQuoted && !aURL.protocol())
|
||||
// throw "Local searches cannot be relative: " + aPath;
|
||||
var URLString = aURL.absoluteString(),
|
||||
existingSearch = FileExecutableSearchesForPaths[isQuoted ? 1 : 0][URLString];
|
||||
|
||||
if (existingSearch)
|
||||
return existingSearch;
|
||||
|
||||
FileExecutableSearchesForPaths[isLocal ? 1 : 0][aPath] = this;
|
||||
|
||||
FileExecutableSearchesForPaths[isQuoted ? 1 : 0][URLString] = this;
|
||||
|
||||
this._UID = objj_generateObjectUID();
|
||||
|
||||
this._URL = aURL;
|
||||
this._isComplete = NO;
|
||||
this._eventDispatcher = new EventDispatcher(this);
|
||||
this._path = aPath;
|
||||
|
||||
this._result = NULL;
|
||||
|
||||
@@ -46,9 +47,9 @@ function FileExecutableSearch(/*String*/ aPath, /*BOOL*/ isLocal)
|
||||
function completed(/*String*/ aStaticResource)
|
||||
{
|
||||
if (!aStaticResource)
|
||||
throw new Error("Could not load file at " + aPath);
|
||||
throw new Error("Could not load file at " + aURL);
|
||||
|
||||
self._result = new FileExecutable(aStaticResource.path());
|
||||
self._result = new FileExecutable(aStaticResource.URL());
|
||||
self._isComplete = YES;
|
||||
|
||||
self._eventDispatcher.dispatchEvent(
|
||||
@@ -58,17 +59,17 @@ function FileExecutableSearch(/*String*/ aPath, /*BOOL*/ isLocal)
|
||||
});
|
||||
}
|
||||
|
||||
if (isLocal || FILE.isAbsolute(aPath))
|
||||
rootResource.resolveSubPath(aPath, NO, completed);
|
||||
if (isQuoted)
|
||||
StaticResource.resolveResourceAtURL(aURL, NO, completed);
|
||||
else
|
||||
StaticResource.resolveStandardNodeAtPath(aPath, completed);
|
||||
StaticResource.resolveResourceAtURLSearchingIncludeURLs(aURL, completed);
|
||||
}
|
||||
|
||||
exports.FileExecutableSearch = FileExecutableSearch;
|
||||
|
||||
FileExecutableSearch.prototype.path = function()
|
||||
FileExecutableSearch.prototype.URL = function()
|
||||
{
|
||||
return this._path;
|
||||
return this._URL;
|
||||
}
|
||||
|
||||
FileExecutableSearch.prototype.result = function()
|
||||
|
||||
@@ -534,30 +534,30 @@ Preprocessor.prototype.implementation = function(tokens, /*StringBuffer*/ aStrin
|
||||
|
||||
Preprocessor.prototype._import = function(tokens)
|
||||
{
|
||||
var path = "",
|
||||
var URLString = "",
|
||||
token = tokens.skip_whitespace(),
|
||||
isLocal = (token != TOKEN_LESS_THAN);
|
||||
isQuoted = (token !== TOKEN_LESS_THAN);
|
||||
|
||||
if (token === TOKEN_LESS_THAN)
|
||||
{
|
||||
while((token = tokens.next()) && token != TOKEN_GREATER_THAN)
|
||||
path += token;
|
||||
while((token = tokens.next()) && token !== TOKEN_GREATER_THAN)
|
||||
URLString += token;
|
||||
|
||||
if(!token)
|
||||
throw new SyntaxError(this.error_message("*** Unterminated import statement."));
|
||||
}
|
||||
|
||||
else if (token.charAt(0) == TOKEN_DOUBLE_QUOTE)
|
||||
path = token.substr(1, token.length - 2);
|
||||
else if (token.charAt(0) === TOKEN_DOUBLE_QUOTE)
|
||||
URLString = token.substr(1, token.length - 2);
|
||||
|
||||
else
|
||||
throw new SyntaxError(this.error_message("*** Expecting '<' or '\"', found \"" + token + "\"."));
|
||||
|
||||
CONCAT(this._buffer, "objj_executeFile(\"");
|
||||
CONCAT(this._buffer, path);
|
||||
CONCAT(this._buffer, isLocal ? "\", true);" : "\", false);");
|
||||
CONCAT(this._buffer, URLString);
|
||||
CONCAT(this._buffer, isQuoted ? "\", YES);" : "\", NO);");
|
||||
|
||||
this._dependencies.push(new FileDependency(path, isLocal));
|
||||
this._dependencies.push(new FileDependency(new CFURL(URLString), isQuoted));
|
||||
}
|
||||
|
||||
Preprocessor.prototype.method = function(/*Lexer*/ tokens)
|
||||
|
||||
+121
-201
@@ -1,124 +1,5 @@
|
||||
|
||||
var FILE =
|
||||
#ifdef COMMONJS
|
||||
require("file");
|
||||
#else
|
||||
{
|
||||
absolute: function(/*String*/ aPath)
|
||||
{
|
||||
aPath = FILE.normal(aPath);
|
||||
|
||||
if (FILE.isAbsolute(aPath))
|
||||
return aPath;
|
||||
|
||||
return FILE.join(FILE.cwd(), aPath);
|
||||
},
|
||||
|
||||
basename: function(/*String*/ aPath)
|
||||
{
|
||||
var components = FILE.split(FILE.normal(aPath));
|
||||
|
||||
return components[components.length - 1];
|
||||
},
|
||||
|
||||
extension: function(/*String*/ aPath)
|
||||
{
|
||||
aPath = FILE.basename(aPath);
|
||||
aPath = aPath.replace(/^\.*/, '');
|
||||
var index = aPath.lastIndexOf(".");
|
||||
return index <= 0 ? "" : aPath.substring(index);
|
||||
},
|
||||
|
||||
cwd: function()
|
||||
{
|
||||
return FILE._cwd;
|
||||
},
|
||||
|
||||
normal: function(/*String*/ aPath)
|
||||
{
|
||||
if (!aPath)
|
||||
return "";
|
||||
|
||||
var components = aPath.split("/"),
|
||||
results = [],
|
||||
index = 0,
|
||||
count = components.length,
|
||||
isRoot = aPath.charAt(0) === "/";
|
||||
|
||||
for (; index < count; ++index)
|
||||
{
|
||||
var component = components[index];
|
||||
|
||||
// These simply remain in the current directory.
|
||||
if (component === "" || component === ".")
|
||||
continue;
|
||||
|
||||
if (component !== "..")
|
||||
{
|
||||
results.push(component);
|
||||
continue;
|
||||
}
|
||||
|
||||
var resultsCount = results.length;
|
||||
|
||||
// If we have a valid previous component, "climb" it.
|
||||
if (resultsCount > 0 && results[resultsCount - 1] !== "..")
|
||||
results.pop();
|
||||
|
||||
// If this isn't a root listing, and we are preceded by only ..'s, or
|
||||
// nothing at all, then add it since it makes sense for relative paths.
|
||||
else if (!isRoot && resultsCount === 0 || results[resultsCount - 1] === "..")
|
||||
results.push(component);
|
||||
}
|
||||
|
||||
return (isRoot ? "/" : "") + results.join("/");
|
||||
},
|
||||
|
||||
dirname: function(/*String*/ aPath)
|
||||
{
|
||||
var aPath = FILE.normal(aPath),
|
||||
components = FILE.split(aPath);
|
||||
|
||||
if (components.length === 2)
|
||||
components.unshift("");
|
||||
|
||||
return FILE.join.apply(FILE, components.slice(0, components.length - 1));
|
||||
},
|
||||
|
||||
isAbsolute: function(/*String*/ aPath)
|
||||
{
|
||||
return aPath.charAt(0) === "/";
|
||||
},
|
||||
|
||||
join: function()
|
||||
{
|
||||
if (arguments.length === 1 && arguments[0] === "")
|
||||
return "/";
|
||||
|
||||
return FILE.normal(Array.prototype.join.call(arguments, "/"));
|
||||
},
|
||||
|
||||
split: function(/*String*/ aPath)
|
||||
{
|
||||
return FILE.normal(aPath).split("/");
|
||||
}
|
||||
}
|
||||
|
||||
var path = window.location.pathname,
|
||||
DOMBaseElement = document.getElementsByTagName("base")[0];
|
||||
|
||||
if (DOMBaseElement)
|
||||
path = DOMBaseElement.getAttribute("href");
|
||||
|
||||
// If this is a directory, then use it as our relative path.
|
||||
if (path.charAt(path.length - 1) === "/")
|
||||
FILE._cwd = path;
|
||||
|
||||
// If not, use it's parent.
|
||||
else
|
||||
FILE._cwd = FILE.dirname(path);
|
||||
|
||||
#endif
|
||||
var rootResources = { };
|
||||
|
||||
function StaticResource(/*String*/ aName, /*StaticResource*/ aParent, /*BOOL*/ isDirectory, /*BOOL*/ isResolved)
|
||||
{
|
||||
@@ -127,7 +8,13 @@ function StaticResource(/*String*/ aName, /*StaticResource*/ aParent, /*BOOL*/ i
|
||||
|
||||
this._name = aName;
|
||||
this._isResolved = !!isResolved;
|
||||
this._path = FILE.join(aParent ? aParent.path() : "", aName);
|
||||
this._URL = new CFURL(aName, aParent && aParent.URL().asDirectoryPathURL());
|
||||
|
||||
if (isDirectory)
|
||||
this._URL = this._URL.asDirectoryPathURL();
|
||||
|
||||
if (!aParent)
|
||||
rootResources[aName] = this;
|
||||
|
||||
this._isDirectory = !!isDirectory;
|
||||
this._isNotFound = NO;
|
||||
@@ -142,6 +29,11 @@ function StaticResource(/*String*/ aName, /*StaticResource*/ aParent, /*BOOL*/ i
|
||||
this._contents = "";
|
||||
}
|
||||
|
||||
StaticResource.rootResources = function()
|
||||
{
|
||||
return rootResources;
|
||||
}
|
||||
|
||||
exports.StaticResource = StaticResource;
|
||||
|
||||
function resolveStaticResource(/*StaticResource*/ aResource)
|
||||
@@ -158,7 +50,7 @@ StaticResource.prototype.resolve = function()
|
||||
{
|
||||
if (this.isDirectory())
|
||||
{
|
||||
var bundle = new CFBundle(this.path());
|
||||
var bundle = new CFBundle(this.URL());
|
||||
|
||||
// Eat any errors.
|
||||
bundle.onerror = function() { };
|
||||
@@ -182,7 +74,7 @@ StaticResource.prototype.resolve = function()
|
||||
resolveStaticResource(self);
|
||||
}
|
||||
|
||||
new FileRequest(this.path(), onsuccess, onfailure);
|
||||
new FileRequest(this.URL(), onsuccess, onfailure);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -191,9 +83,9 @@ StaticResource.prototype.name = function()
|
||||
return this._name;
|
||||
}
|
||||
|
||||
StaticResource.prototype.path = function()
|
||||
StaticResource.prototype.URL = function()
|
||||
{
|
||||
return this._path;
|
||||
return this._URL;
|
||||
}
|
||||
|
||||
StaticResource.prototype.contents = function()
|
||||
@@ -221,50 +113,88 @@ StaticResource.prototype.write = function(/*String*/ aString)
|
||||
this._contents += aString;
|
||||
}
|
||||
|
||||
StaticResource.prototype.resolveSubPath = function(/*String*/ aPath, /*BOOL*/ isDirectory, /*Function*/ aCallback)
|
||||
function rootResourceForAbsoluteURL(/*CFURL*/ anAbsoluteURL)
|
||||
{
|
||||
aPath = FILE.normal(aPath);
|
||||
var schemeAndAuthority = anAbsoluteURL.schemeAndAuthority(),
|
||||
resource = rootResources[schemeAndAuthority];
|
||||
|
||||
if (aPath === "/")
|
||||
return aCallback(rootResource);
|
||||
if (!resource)
|
||||
resource = new StaticResource(schemeAndAuthority, NULL, YES, YES);
|
||||
|
||||
if (!FILE.isAbsolute(aPath))
|
||||
aPath = FILE.join(this.path(), aPath);
|
||||
|
||||
var components = FILE.split(aPath),
|
||||
index = this === rootResource ? 1 : FILE.split(this.path()).length;
|
||||
|
||||
resolvePathComponents(this, isDirectory, components, index, aCallback);
|
||||
return resource;
|
||||
}
|
||||
|
||||
function resolvePathComponents(/*StaticResource*/ startResource, /*BOOL*/ isDirectory, /*Array*/ components, /*Integer*/ index, /*Function*/ aCallback)
|
||||
function resolveURL(/*CFURL|String*/ aURL)
|
||||
{
|
||||
var count = components.length,
|
||||
parent = startResource;
|
||||
return new CFURL(aURL, mainBundleURL);
|
||||
}
|
||||
|
||||
function continueResolution()
|
||||
StaticResource.resourceAtURL = function(/*CFURL*/ aURL, /*BOOL*/ resolveAsDirectoriesIfNecessary)
|
||||
{
|
||||
aURL = resolveURL(aURL).absoluteURL();
|
||||
|
||||
var resource = rootResourceForAbsoluteURL(aURL),
|
||||
components = aURL.pathComponents(),
|
||||
index = 0,
|
||||
count = components.length;
|
||||
|
||||
for (; index < count; ++index)
|
||||
{
|
||||
resolvePathComponents(parent, isDirectory, components, index, aCallback);
|
||||
var name = components[index];
|
||||
|
||||
if (hasOwnProperty.call(resource._children, name))
|
||||
resource = resource._children[name];
|
||||
|
||||
else if (resolveAsDirectoriesIfNecessary)
|
||||
resource = new StaticResource(name, resource, YES, YES);
|
||||
|
||||
else
|
||||
throw new Error("Static Resource at " + aURL + " is not resolved (\"" + name + "\")");
|
||||
}
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
||||
StaticResource.prototype.resourceAtURL = function(/*CFURL|String*/ aURL, /*BOOL*/ resolveAsDirectoriesIfNecessary)
|
||||
{
|
||||
return StaticResource.resourceAtURL(new CFURL(aURL, this.URL()), resolveAsDirectoriesIfNecessary);
|
||||
}
|
||||
|
||||
StaticResource.resolveResourceAtURL = function(/*CFURL*/ aURL, /*BOOL*/ isDirectory, /*Function*/ aCallback)
|
||||
{
|
||||
aURL = resolveURL(aURL).absoluteURL();
|
||||
|
||||
resolveResourceComponents(rootResourceForAbsoluteURL(aURL), isDirectory, aURL.pathComponents(), 0, aCallback);
|
||||
}
|
||||
|
||||
StaticResource.prototype.resolveResourceAtURL = function(/*CFURL|String*/ aURL, /*BOOL*/ isDirectory, /*Function*/ aCallback)
|
||||
{
|
||||
StaticResource.resolveResourceAtURL(new CFURL(aURL, this.URL()).absoluteURL(), isDirectory, aCallback);
|
||||
}
|
||||
|
||||
function resolveResourceComponents(/*StaticResource*/ aResource, /*BOOL*/ isDirectory, /*Array*/ components, /*Integer*/ index, /*Function*/ aCallback)
|
||||
{
|
||||
var count = components.length;
|
||||
|
||||
for (; index < count; ++index)
|
||||
{
|
||||
var name = components[index],
|
||||
child = parent._children[name];
|
||||
//CPLog(index + " " + components + ":" + (childNode && childNode.isResolved()) + ":");
|
||||
//CPLog(name + " of " + parentNode.name() + " " + (childNode && childNode.name()));
|
||||
//CPLog(parentNode._childNodes);
|
||||
// + "(" + components + ")" + " " + index + "/" + count + ":" + (childNode && childNode.name()) +">" + (childNode ? 1:0) + " " + (childNode && childNode.isResolved()));
|
||||
child = hasOwnProperty.call(aResource._children, name) && aResource._children[name];
|
||||
|
||||
// If the child doesn't exist, create and resolve it.
|
||||
if (!child)
|
||||
{
|
||||
child = new StaticResource(name, parent, index + 1 < count || isDirectory , NO);
|
||||
child = new StaticResource(name, aResource, index + 1 < count || isDirectory , NO);
|
||||
child.resolve();
|
||||
}
|
||||
|
||||
// If this resource is still being resolved, just wait and rerun this same method when it's ready.
|
||||
if (!child.isResolved())
|
||||
return child.addEventListener("resolve", continueResolution);
|
||||
return child.addEventListener("resolve", function()
|
||||
{
|
||||
// Continue resolving once this is done.
|
||||
resolveResourceComponents(aResource, isDirectory, components, index, aCallback);
|
||||
});
|
||||
|
||||
// If we've already determined that this file doesn't exist...
|
||||
if (child.isNotFound())
|
||||
@@ -274,10 +204,36 @@ function resolvePathComponents(/*StaticResource*/ startResource, /*BOOL*/ isDire
|
||||
if ((index + 1 < count) && child.isFile())
|
||||
return aCallback(null, new Error("File is not a directory: " + components.join("/")));
|
||||
|
||||
parent = child;
|
||||
aResource = child;
|
||||
}
|
||||
|
||||
return aCallback(parent);
|
||||
aCallback(aResource);
|
||||
}
|
||||
|
||||
function resolveResourceAtURLSearchingIncludeURLs(/*CFURL*/ aURL, /*Number*/ anIndex, /*Function*/ aCallback)
|
||||
{
|
||||
var includeURLs = StaticResource.includeURLs(),
|
||||
searchURL = new CFURL(aURL, includeURLs[anIndex]).absoluteURL();
|
||||
|
||||
StaticResource.resolveResourceAtURL(searchURL, NO, function(/*StaticResource*/ aStaticResource)
|
||||
{
|
||||
if (!aStaticResource)
|
||||
{
|
||||
if (anIndex + 1 < includeURLs.length)
|
||||
resolveResourceAtURLSearchingIncludeURLs(aURL, anIndex + 1, aCallback);
|
||||
else
|
||||
aCallback(NULL);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
aCallback(aStaticResource);
|
||||
});
|
||||
}
|
||||
|
||||
StaticResource.resolveResourceAtURLSearchingIncludeURLs = function(/*CFURL*/ aURL, /*Function*/ aCallback)
|
||||
{
|
||||
resolveResourceAtURLSearchingIncludeURLs(aURL, 0, aCallback);
|
||||
}
|
||||
|
||||
StaticResource.prototype.addEventListener = function(/*String*/ anEventName, /*Function*/ anEventListener)
|
||||
@@ -310,7 +266,7 @@ StaticResource.prototype.toString = function(/*BOOL*/ includeNotFounds)
|
||||
if (this.isNotFound())
|
||||
return "<file not found: " + this.name() + ">";
|
||||
|
||||
var string = this.parent() ? this.name() : "/";
|
||||
var string = this.name();
|
||||
|
||||
if (this.isDirectory())
|
||||
{
|
||||
@@ -329,61 +285,25 @@ StaticResource.prototype.toString = function(/*BOOL*/ includeNotFounds)
|
||||
return string;
|
||||
}
|
||||
|
||||
StaticResource.prototype.nodeAtSubPath = function(/*String*/ aPath, /*BOOL*/ shouldResolveAsDirectories)
|
||||
var includeURLs = NULL;
|
||||
|
||||
StaticResource.includeURLs = function()
|
||||
{
|
||||
aPath = FILE.normal(aPath);
|
||||
if (includeURLs)
|
||||
return includeURLs;
|
||||
|
||||
var components = FILE.split(FILE.isAbsolute(aPath) ? aPath : FILE.join(this.path(), aPath)),
|
||||
index = 1,
|
||||
count = components.length,
|
||||
parent = rootResource;
|
||||
var includeURLs = [];
|
||||
|
||||
for (; index < count; ++index)
|
||||
{
|
||||
var name = components[index];
|
||||
if (!global.OBJJ_INCLUDE_PATHS && !global.OBJJ_INCLUDE_URLS)
|
||||
includeURLs = ["Frameworks", "Frameworks/Debug"];
|
||||
|
||||
if (hasOwnProperty.call(parent._children, name))
|
||||
parent = parent._children[name];
|
||||
else
|
||||
includeURLs = (global.OBJJ_INCLUDE_PATHS || []).concat(global.OBJJ_INCLUDE_URLS || []);
|
||||
|
||||
else if (shouldResolveAsDirectories)
|
||||
parent = new StaticResource(name, parent, YES, YES);
|
||||
var count = includeURLs.length;
|
||||
|
||||
else
|
||||
throw NULL;
|
||||
}
|
||||
while (count--)
|
||||
includeURLs[count] = new CFURL(includeURLs[count]).asDirectoryPathURL();
|
||||
|
||||
return parent;
|
||||
return includeURLs;
|
||||
}
|
||||
|
||||
StaticResource.resolveStandardNodeAtPath = function(/*String*/ aPath, /*Function*/ aCallback)
|
||||
{
|
||||
var includePaths = StaticResource.includePaths(),
|
||||
resolveStandardNodeAtPath = function(/*String*/ aPath, /*int*/ anIndex)
|
||||
{
|
||||
var searchPath = FILE.absolute(FILE.join(includePaths[anIndex], FILE.normal(aPath)));
|
||||
|
||||
rootResource.resolveSubPath(searchPath, NO, function(/*StaticResource*/ aStaticResource)
|
||||
{
|
||||
if (!aStaticResource)
|
||||
{
|
||||
if (anIndex + 1< includePaths.length)
|
||||
resolveStandardNodeAtPath(aPath, anIndex + 1);
|
||||
else
|
||||
aCallback(NULL);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
aCallback(aStaticResource);
|
||||
});
|
||||
};
|
||||
|
||||
resolveStandardNodeAtPath(aPath, 0);
|
||||
}
|
||||
|
||||
StaticResource.includePaths = function()
|
||||
{
|
||||
return global.OBJJ_INCLUDE_PATHS || ["Frameworks", "Frameworks/Debug"];
|
||||
}
|
||||
|
||||
StaticResource.cwd = FILE.cwd();
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
|
||||
@implementation CFURLTest : OJTestCase
|
||||
{
|
||||
}
|
||||
|
||||
- (void)testRelativeURLs
|
||||
{
|
||||
var URLStrings =
|
||||
{
|
||||
"g:h" : "g:h",
|
||||
"g" : "http://a/b/c/g",
|
||||
"./g" : "http://a/b/c/g",
|
||||
"g/" : "http://a/b/c/g/",
|
||||
"/g" : "http://a/g",
|
||||
//"//g" : "http://g",
|
||||
"?y" : "http://a/b/c/?y",
|
||||
"g?y" : "http://a/b/c/g?y",
|
||||
//"#s" : "(current document)#s",
|
||||
"g#s" : "http://a/b/c/g#s",
|
||||
"g?y#s" : "http://a/b/c/g?y#s",
|
||||
";x" : "http://a/b/c/;x",
|
||||
"g;x" : "http://a/b/c/g;x",
|
||||
"g;x?y#s" : "http://a/b/c/g;x?y#s",
|
||||
"." : "http://a/b/c/",
|
||||
"./" : "http://a/b/c/",
|
||||
".." : "http://a/b/",
|
||||
"../" : "http://a/b/",
|
||||
"../g" : "http://a/b/g",
|
||||
"../.." : "http://a/",
|
||||
"../../" : "http://a/",
|
||||
"../../g" : "http://a/g",
|
||||
"../../../g" : "http://a/../g",
|
||||
"../../../../g" : "http://a/g",//"http://a/../../g",
|
||||
"/./g" : "http://a/g",//"http://a/./g",
|
||||
// "/../g" : "http://a/g",//"http://a/../g",
|
||||
"g." : "http://a/b/c/g.",
|
||||
".g" : "http://a/b/c/.g",
|
||||
"g.." : "http://a/b/c/g..",
|
||||
"..g" : "http://a/b/c/..g",
|
||||
"./../g" : "http://a/b/g",
|
||||
"./g/." : "http://a/b/c/g/",
|
||||
"g/./h" : "http://a/b/c/g/h",
|
||||
"g/../h" : "http://a/b/c/h",
|
||||
"g;x=1/./y" : "http://a/b/c/g;x=1/y",
|
||||
"g;x=1/../y" : "http://a/b/c/y",
|
||||
"g?y/./x" : "http://a/b/c/g?y/./x",
|
||||
"g?y/../x" : "http://a/b/c/g?y/../x",
|
||||
"g#s/./x" : "http://a/b/c/g#s/./x",
|
||||
"g#s/../x" : "http://a/b/c/g#s/../x"
|
||||
};
|
||||
|
||||
var URLString,
|
||||
baseURL = new CFURL("http://a/b/c/d;p?q");
|
||||
|
||||
for (URLString in URLStrings)
|
||||
if (URLStrings.hasOwnProperty(URLString))
|
||||
{
|
||||
print(URLStrings[URLString] + " " + new CFURL(URLString, baseURL).absoluteString());
|
||||
[self assert:URLStrings[URLString] equals:new CFURL(URLString, baseURL).absoluteString()];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
Reference in New Issue
Block a user