diff --git a/Foundation/CPBundle.j b/Foundation/CPBundle.j
index 202781a71..b2c4fd4e4 100644
--- a/Foundation/CPBundle.j
+++ b/Foundation/CPBundle.j
@@ -113,7 +113,7 @@ var CPBundlesForPaths = { };
- (id)objectForInfoDictionaryKey:(CPString)aKey
{
- return _bundle.valueForInfoDictionary(aKey);
+ return _bundle.valueForInfoDictionaryKey(aKey);
}
//
diff --git a/Foundation/CPURL.j b/Foundation/CPURL.j
index fc7a52405..e5ef1e3e2 100644
--- a/Foundation/CPURL.j
+++ b/Foundation/CPURL.j
@@ -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];
diff --git a/Objective-J/Bootstrap.js b/Objective-J/Bootstrap.js
index 598867210..26b526b6a 100644
--- a/Objective-J/Bootstrap.js
+++ b/Objective-J/Bootstrap.js
@@ -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 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();
diff --git a/Objective-J/CFBundle.js b/Objective-J/CFBundle.js
index bb535e2b5..bc1d7e401 100644
--- a/Objective-J/CFBundle.js
+++ b/Objective-J/CFBundle.js
@@ -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();
+}
diff --git a/Objective-J/CFHTTPRequest.js b/Objective-J/CFHTTPRequest.js
index 51c76cea1..17199af09 100644
--- a/Objective-J/CFHTTPRequest.js
+++ b/Objective-J/CFHTTPRequest.js
@@ -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
diff --git a/Objective-J/CFURL.js b/Objective-J/CFURL.js
index 0ed479eca..50c2af6fd 100644
--- a/Objective-J/CFURL.js
+++ b/Objective-J/CFURL.js
@@ -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;
diff --git a/Objective-J/CommonJS/lib/objective-j.js b/Objective-J/CommonJS/lib/objective-j.js
index 70962bb9a..c1778c65f 100644
--- a/Objective-J/CommonJS/lib/objective-j.js
+++ b/Objective-J/CommonJS/lib/objective-j.js
@@ -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");
});
diff --git a/Objective-J/EventDispatcher.js b/Objective-J/EventDispatcher.js
index 47f9bcc3b..048ef3540 100644
--- a/Objective-J/EventDispatcher.js
+++ b/Objective-J/EventDispatcher.js
@@ -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--)
diff --git a/Objective-J/Executable.js b/Objective-J/Executable.js
index 2e3b81a40..490951e85 100644
--- a/Objective-J/Executable.js
+++ b/Objective-J/Executable.js
@@ -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;
}
-
diff --git a/Objective-J/FileDependency.js b/Objective-J/FileDependency.js
index 2fdd851d4..c65861f7b 100644
--- a/Objective-J/FileDependency.js
+++ b/Objective-J/FileDependency.js
@@ -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();
}
diff --git a/Objective-J/FileExecutable.js b/Objective-J/FileExecutable.js
index 478060f8e..18c7d477d 100644
--- a/Objective-J/FileExecutable.js
+++ b/Objective-J/FileExecutable.js
@@ -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);
diff --git a/Objective-J/FileExecutableSearch.js b/Objective-J/FileExecutableSearch.js
index 395e2f6c7..1314c8cc1 100644
--- a/Objective-J/FileExecutableSearch.js
+++ b/Objective-J/FileExecutableSearch.js
@@ -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()
diff --git a/Objective-J/Preprocessor.js b/Objective-J/Preprocessor.js
index 54e5d97c7..22b0924f9 100644
--- a/Objective-J/Preprocessor.js
+++ b/Objective-J/Preprocessor.js
@@ -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)
diff --git a/Objective-J/StaticResource.js b/Objective-J/StaticResource.js
index 238a8d718..02537ff4b 100644
--- a/Objective-J/StaticResource.js
+++ b/Objective-J/StaticResource.js
@@ -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 "";
- 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();
diff --git a/Tests/Objective-J/CFURLTest.j b/Tests/Objective-J/CFURLTest.j
new file mode 100644
index 000000000..f168bdfed
--- /dev/null
+++ b/Tests/Objective-J/CFURLTest.j
@@ -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