From fa2ea8f8097e01f3cfd3eb55c4f04b330e67d1ac Mon Sep 17 00:00:00 2001 From: cacaodev Date: Fri, 1 Apr 2022 12:17:50 +0200 Subject: [PATCH] Revert "Revert "New: Support to compile deep structured project in the web browser"" --- AppKit/Info.plist | 216 ++++++++++++- CommonJS/bin/flatten | 2 +- Foundation/Info.plist | 57 ++++ Objective-J/Bootstrap.js | 18 +- Objective-J/CFBundle.js | 4 + Objective-J/CFDictionary.js | 19 ++ Objective-J/CommonJS/lib/objective-j.js | 24 +- .../CommonJS/lib/objective-j/compiler.js | 2 +- .../lib/objective-j/jake/bundletask.js | 2 +- Objective-J/Executable.js | 97 +++--- Objective-J/FileExecutable.js | 301 +---------------- Objective-J/OldBrowserCompatibility.js | 31 ++ Objective-J/StaticResource.js | 306 ++++++++++++++++-- 13 files changed, 705 insertions(+), 374 deletions(-) diff --git a/AppKit/Info.plist b/AppKit/Info.plist index ed261efba..92b57eba2 100644 --- a/AppKit/Info.plist +++ b/AppKit/Info.plist @@ -2,13 +2,213 @@ - CPBundleIdentifier - com.280n.AppKit - CPBundleInfoDictionaryVersion - 6.0 - CPBundleName - AppKit - CPBundlePackageType - FMWK + CPBundleIdentifier + com.280n.AppKit + CPBundleInfoDictionaryVersion + 6.0 + CPBundleName + AppKit + CPBundlePackageType + FMWK + CPCompileIncludeFileArray + + Platform/Platform.h + Platform/DOM/CPDOMDisplayServer.h + + CPFileTranslationDictionary + + _CPCibCustomObject.j + Cib/_CPCibCustomObject.j + _CPCibCustomView.j + Cib/_CPCibCustomView.j + CPCib.j + Cib/CPCib.j + _CPLocalizableString.j + Cib/_CPLocalizableString.j + CPCibConnector.j + Cib/CPCibConnector.j + CPCibHelpConnector.j + Cib/CPCibHelpConnector.j + _CPCibCustomResource.j + Cib/_CPCibCustomResource.j + _CPCibProxyObject.j + Cib/_CPCibProxyObject.j + _CPCibObjectData.j + Cib/_CPCibObjectData.j + CPCibLoading.j + Cib/CPCibLoading.j + _CPCibWindowTemplate.j + Cib/_CPCibWindowTemplate.j + CPCibRuntimeAttributesConnector.j + Cib/CPCibRuntimeAttributesConnector.j + _CPCibClassSwapper.j + Cib/_CPCibClassSwapper.j + CPCibControlConnector.j + Cib/CPCibControlConnector.j + CPCibOutletConnector.j + Cib/CPCibOutletConnector.j + _CPCibKeyedUnarchiver.j + Cib/_CPCibKeyedUnarchiver.j + CPCibBindingConnector.j + Cib/CPCibBindingConnector.j + + _CPObjectAnimator.j + CoreAnimation/_CPObjectAnimator.j + CAAnimation.j + CoreAnimation/CAAnimation.j + CABackingStore.j + CoreAnimation/CABackingStore.j + CABasicAnimation.j + CoreAnimation/CABasicAnimation.j + CAFlashLayer.j + CoreAnimation/CAFlashLayer.j + CAKeyframeAnimation.j + CoreAnimation/CAKeyframeAnimation.j + CALayer.j + CoreAnimation/CALayer.j + CAMediaTimingFunction.j + CoreAnimation/CAMediaTimingFunction.j + CAPropertyAnimation.j + CoreAnimation/CAPropertyAnimation.j + CPAnimationContext.j + CoreAnimation/CPAnimationContext.j + CPViewAnimator.j + CoreAnimation/CPViewAnimator.j + CSSAnimation.j + CoreAnimation/CSSAnimation.j + + CGGradient.j + CoreGraphics/CGGradient.j + CGContextText.j + CoreGraphics/CGContextText.j + CGAffineTransform.j + CoreGraphics/CGAffineTransform.j + CGColorSpace.j + CoreGraphics/CGColorSpace.j + CGContext.j + CoreGraphics/CGContext.j + CGGeometry.j + CoreGraphics/CGGeometry.j + CGContextVML.j + CoreGraphics/CGContextVML.j + CGPath.j + CoreGraphics/CGPath.j + CGContextCanvas.j + CoreGraphics/CGContextCanvas.j + CGColor.j + CoreGraphics/CGColor.j + + _CPDatePickerCalendar.j + CPDatePicker/_CPDatePickerCalendar.j + _CPDatePickerTextField.j + CPDatePicker/_CPDatePickerTextField.j + _CPDatePickerClock.j + CPDatePicker/_CPDatePickerClock.j + CPDatePicker.j + CPDatePicker/CPDatePicker.j + + _CPMenuWindow.j + CPMenu/_CPMenuWindow.j + CPMenu.j + CPMenu/CPMenu.j + _CPMenuManager.j + CPMenu/_CPMenuManager.j + _CPMenuBarWindow.j + CPMenu/_CPMenuBarWindow.j + + CPMenuItem.j + CPMenuItem/CPMenuItem.j + _CPMenuItemView.j + CPMenuItem/_CPMenuItemView.j + _CPMenuItemStandardView.j + CPMenuItem/_CPMenuItemStandardView.j + _CPMenuItemSeparatorView.j + CPMenuItem/_CPMenuItemSeparatorView.j + _CPMenuItemMenuBarView.j + CPMenuItem/_CPMenuItemMenuBarView.j + + _CPRuleEditorViewSliceRow.j + CPRuleEditor/_CPRuleEditorViewSliceRow.j + CPPredicateEditor.j + CPRuleEditor/CPPredicateEditor.j + CPRuleEditor.j + CPRuleEditor/CPRuleEditor.j + _CPRuleEditorLocalizer.j + CPRuleEditor/_CPRuleEditorLocalizer.j + CPPredicateEditorRowTemplate.j + CPRuleEditor/CPPredicateEditorRowTemplate.j + _CPRuleEditorViewSlice.j + CPRuleEditor/_CPRuleEditorViewSlice.j + CPRuleEditor_Constants.j + CPRuleEditor/CPRuleEditor_Constants.j + _CPPredicateEditorRowNode.j + CPRuleEditor/_CPPredicateEditorRowNode.j + _CPPredicateEditorTree.j + CPRuleEditor/_CPPredicateEditorTree.j + + CPTextStorage.j + CPTextView/CPTextStorage.j + _CPRTFParser.j + CPTextView/_CPRTFParser.j + _CPRTFProducer.j + CPTextView/_CPRTFProducer.j + CPTextContainer.j + CPTextView/CPTextContainer.j + CPLayoutManager.j + CPTextView/CPLayoutManager.j + CPTextView.j + CPTextView/CPTextView.j + CPFontDescriptor.j + CPTextView/CPFontDescriptor.j + CPFontPanel.j + CPTextView/CPFontPanel.j + CPParagraphStyle.j + CPTextView/CPParagraphStyle.j + CPTypesetter.j + CPTextView/CPTypesetter.j + + CPWindow_Constants.j + CPWindow/CPWindow_Constants.j + _CPStandardWindowView.j + CPWindow/_CPStandardWindowView.j + _CPShadowWindowView.j + CPWindow/_CPShadowWindowView.j + _CPToolTipWindowView.j + CPWindow/_CPToolTipWindowView.j + _CPBorderlessWindowView.j + CPWindow/_CPBorderlessWindowView.j + _CPBorderlessBridgeWindowView.j + CPWindow/_CPBorderlessBridgeWindowView.j + _CPDocModalWindowView.j + CPWindow/_CPDocModalWindowView.j + _CPModalWindowView.j + CPWindow/_CPModalWindowView.j + _CPPopoverWindowView.j + CPWindow/_CPPopoverWindowView.j + _CPWindowView.j + CPWindow/_CPWindowView.j + _CPTitleableWindowView.j + CPWindow/_CPTitleableWindowView.j + CPWindow.j + CPWindow/CPWindow.j + _CPHUDWindowView.j + CPWindow/_CPHUDWindowView.j + + CPPlatform.j + Platform/CPPlatform.j + CPPlatformString.j + Platform/CPPlatformString.j + CPPlatformWindow.j + Platform/CPPlatformWindow.j + CPPlatformWindow+DOM.j + Platform/DOM/CPPlatformWindow+DOM.j + CPPlatformPasteboard.j + Platform/DOM/CPPlatformPasteboard.j + CPDOMWindowLayer.j + Platform/DOM/CPDOMWindowLayer.j + CPPlatformWindow+DOMKeys.j + Platform/DOM/CPPlatformWindow+DOMKeys.j + + diff --git a/CommonJS/bin/flatten b/CommonJS/bin/flatten index 80b9ecf8e..1df033252 100755 --- a/CommonJS/bin/flatten +++ b/CommonJS/bin/flatten @@ -233,7 +233,7 @@ ObjectiveJFlattener.prototype.serializeFunctions = function() { var functionString = executable._function.toString().replace(", require, exports, module, system, print, window", ""); // HACK var relative = this.rootPath.relative(path).toString(); - this.functionsBuffer.push("ObjectiveJ.FileExecutable._cacheFunction(new CFURL("+JSON.stringify(relative)+", baseURL),\n"+functionString+");"); + this.functionsBuffer.push("ObjectiveJ.StaticResource._cacheFunction(new CFURL("+JSON.stringify(relative)+", baseURL),\n"+functionString+");"); } var bundle = this.context.global.CFBundle.bundleContainingURL(path); diff --git a/Foundation/Info.plist b/Foundation/Info.plist index c16e019ed..403d62c27 100644 --- a/Foundation/Info.plist +++ b/Foundation/Info.plist @@ -10,5 +10,62 @@ Foundation CPBundlePackageType FMWK + CPFileTranslationDictionary + + _CPAggregateExpression.j + CPPredicate/_CPAggregateExpression.j + _CPSelfExpression.j + CPPredicate/_CPSelfExpression.j + _CPSubqueryExpression.j + CPPredicate/_CPSubqueryExpression.j + _CPConstantValueExpression.j + CPPredicate/_CPConstantValueExpression.j + CPCompoundPredicate_Constants.j + CPPredicate/CPCompoundPredicate_Constants.j + _CPSetExpression.j + CPPredicate/_CPSetExpression.j + CPCompoundPredicate.j + CPPredicate/CPCompoundPredicate.j + _CPKeyPathExpression.j + CPPredicate/_CPKeyPathExpression.j + CPComparisonPredicate.j + CPPredicate/CPComparisonPredicate.j + _CPPredicate.j + CPPredicate/_CPPredicate.j + _CPFunctionExpression.j + CPPredicate/_CPFunctionExpression.j + _CPExpression.j + CPPredicate/_CPExpression.j + CPExpression.j + CPPredicate/CPExpression.j + _CPBlockExpression.j + CPPredicate/_CPBlockExpression.j + _CPConditionalExpression.j + CPPredicate/_CPConditionalExpression.j + CPComparisonPredicate_Constants.j + CPPredicate/CPComparisonPredicate_Constants.j + CPPredicate.j + CPPredicate/CPPredicate.j + _CPVariableExpression.j + CPPredicate/_CPVariableExpression.j + + _CPConcreteMutableSet.j + CPSet/_CPConcreteMutableSet.j + _CPSet.j + CPSet/_CPSet.j + CPSet.j + CPSet/CPSet.j + CPMutableSet.j + CPSet/CPMutableSet.j + + _CPArray.j + CPArray/_CPArray.j + _CPJavaScriptArray.j + CPArray/_CPJavaScriptArray.j + CPArray.j + CPArray/CPArray.j + CPMutableArray.j + CPArray/CPMutableArray.j + diff --git a/Objective-J/Bootstrap.js b/Objective-J/Bootstrap.js index 7f7be575f..80293fb11 100644 --- a/Objective-J/Bootstrap.js +++ b/Objective-J/Bootstrap.js @@ -52,7 +52,9 @@ if (typeof OBJJ_COMPILER_FLAGS !== 'undefined') var flags = {}; for (var i = 0; i < OBJJ_COMPILER_FLAGS.length; i++) { - switch (OBJJ_COMPILER_FLAGS[i]) + var aFlag = OBJJ_COMPILER_FLAGS[i]; + + switch (aFlag) { case "IncludeDebugSymbols": flags.includeMethodFunctionNames = true; @@ -70,9 +72,21 @@ if (typeof OBJJ_COMPILER_FLAGS !== 'undefined') case "SourceMap": flags.sourceMap = true; break; + + case "SourceMapIncludeSource": + flags.sourceMapIncludeSource = true; + break; + + default: + if (aFlag.indexOf("-D") === 0) { + var macroDefinition = aFlag.substring(2); + + (flags.macros || (flags.macros = [])).push(macroDefinition); + } + break; } } - FileExecutable.setCurrentCompilerFlags(flags); + StaticResource.setCurrentCompilerFlags(flags); } // Turn the main file into a URL. diff --git a/Objective-J/CFBundle.js b/Objective-J/CFBundle.js index 5133d08d0..2a1eb3ec4 100644 --- a/Objective-J/CFBundle.js +++ b/Objective-J/CFBundle.js @@ -828,7 +828,11 @@ function decompileStaticFile(/*Bundle*/ aBundle, /*String*/ aString, /*String*/ } else if (marker === MARKER_TEXT) + { file.write(text); + if (text.match(/^@STATIC;/)) + file.decompile(); + } } } diff --git a/Objective-J/CFDictionary.js b/Objective-J/CFDictionary.js index c3ff941ae..1d1ce90d9 100644 --- a/Objective-J/CFDictionary.js +++ b/Objective-J/CFDictionary.js @@ -152,6 +152,25 @@ CFDictionary.prototype.toString = function() DISPLAY_NAME(CFDictionary.prototype.toString); +CFDictionary.prototype.toJSObject = function() +{ + var jsObject = new Object(), + keys = this._keys, + index = 0, + count = this._count; + + for (; index < count; ++index) + { + var key = keys[index]; + + jsObject[key] = this.valueForKey(key); + } + + return jsObject; +}; + +DISPLAY_NAME(CFDictionary.prototype.toJSObject); + GLOBAL(CFMutableDictionary) = function(/*CFDictionary*/ aDictionary) { CFDictionary.apply(this, []); diff --git a/Objective-J/CommonJS/lib/objective-j.js b/Objective-J/CommonJS/lib/objective-j.js index b610953ca..643f8f3a7 100644 --- a/Objective-J/CommonJS/lib/objective-j.js +++ b/Objective-J/CommonJS/lib/objective-j.js @@ -129,51 +129,51 @@ exports.run = function(args) case "-g": case "--include-debug-symbols": argv.shift(); - var flags = ObjectiveJ.FileExecutable.currentCompilerFlags(); + var flags = ObjectiveJ.StaticResource.currentCompilerFlags(); flags.includeMethodFunctionNames = true; - ObjectiveJ.FileExecutable.setCurrentCompilerFlags(flags); + ObjectiveJ.StaticResource.setCurrentCompilerFlags(flags); break; case "-T": case "--dont-include-type-signatures": argv.shift(); - var flags = ObjectiveJ.FileExecutable.currentCompilerFlags(); + var flags = ObjectiveJ.StaticResource.currentCompilerFlags(); flags.includeIvarTypeSignatures = true; flags.includeMethodArgumentTypeSignatures = true; - ObjectiveJ.FileExecutable.setCurrentCompilerFlags(flags); + ObjectiveJ.StaticResource.setCurrentCompilerFlags(flags); break; case "-O2": case "--inline-msg-send": argv.shift(); - var flags = ObjectiveJ.FileExecutable.currentCompilerFlags(); + var flags = ObjectiveJ.StaticResource.currentCompilerFlags(); flags.inlineMsgSendFunctions = true; - ObjectiveJ.FileExecutable.setCurrentCompilerFlags(flags); + ObjectiveJ.StaticResource.setCurrentCompilerFlags(flags); break; case "-g": case "--include-debug-symbols": argv.shift(); - var flags = ObjectiveJ.FileExecutable.currentCompilerFlags(); + var flags = ObjectiveJ.StaticResource.currentCompilerFlags(); flags.includeMethodFunctionNames = true; - ObjectiveJ.FileExecutable.setCurrentCompilerFlags(flags); + ObjectiveJ.StaticResource.setCurrentCompilerFlags(flags); break; case "-T": case "--dont-include-type-signatures": argv.shift(); - var flags = ObjectiveJ.FileExecutable.currentCompilerFlags(); + var flags = ObjectiveJ.StaticResource.currentCompilerFlags(); flags.includeIvarTypeSignatures = true; flags.includeMethodArgumentTypeSignatures = true; - ObjectiveJ.FileExecutable.setCurrentCompilerFlags(flags); + ObjectiveJ.StaticResource.setCurrentCompilerFlags(flags); break; case "-O2": case "--inline-msg-send": argv.shift(); - var flags = ObjectiveJ.FileExecutable.currentCompilerFlags(); + var flags = ObjectiveJ.StaticResource.currentCompilerFlags(); flags.inlineMsgSendFunctions = true; - ObjectiveJ.FileExecutable.setCurrentCompilerFlags(flags); + ObjectiveJ.StaticResource.setCurrentCompilerFlags(flags); break; default: diff --git a/Objective-J/CommonJS/lib/objective-j/compiler.js b/Objective-J/CommonJS/lib/objective-j/compiler.js index 606b8eaf2..ec6ceaa38 100644 --- a/Objective-J/CommonJS/lib/objective-j/compiler.js +++ b/Objective-J/CommonJS/lib/objective-j/compiler.js @@ -113,7 +113,7 @@ function compileWithResolvedFlags(aFilePath, objjcFlags, gccFlags, asPlainJavasc } } - ObjectiveJ.FileExecutable.setCurrentCompilerFlags(objjcFlags); + ObjectiveJ.StaticResource.setCurrentCompilerFlags(objjcFlags); ObjectiveJ.make_narwhal_factory(absolutePath, basePath, translateFilenameToPath)(require, {}, module, system, print); executable = new ObjectiveJ.FileExecutable(FILE.basename(aFilePath)); diff --git a/Objective-J/CommonJS/lib/objective-j/jake/bundletask.js b/Objective-J/CommonJS/lib/objective-j/jake/bundletask.js index 136a8388e..80653582a 100644 --- a/Objective-J/CommonJS/lib/objective-j/jake/bundletask.js +++ b/Objective-J/CommonJS/lib/objective-j/jake/bundletask.js @@ -907,7 +907,7 @@ BundleTask.prototype.defineSourceTasks = function() basePath = absolutePath.substring(0, absolutePath.length - theTranslatedFilename.length); // Here we set the current compiler flags so the load system will know what compiler flags to use - ObjectiveJ.FileExecutable.setCurrentGccCompilerFlags(environmentCompilerFlags); + ObjectiveJ.StaticResource.setCurrentGccCompilerFlags(environmentCompilerFlags); // Here we tell the CFBundle to load frameworks for the current build enviroment and not the enviroment that is running CFBundle.environments = function() {return [anEnvironment.name(), "ObjJ"]}; ObjectiveJ.make_narwhal_factory(absolutePath, basePath, translateFilenameToPath)(require, e, module, system, print); diff --git a/Objective-J/Executable.js b/Objective-J/Executable.js index 17dd66a02..f702aa146 100644 --- a/Objective-J/Executable.js +++ b/Objective-J/Executable.js @@ -24,8 +24,7 @@ var ExecutableUnloadedFileDependencies = 0, ExecutableLoadingFileDependencies = 1, ExecutableLoadedFileDependencies = 2, - ExecutableCantStartLoadYetFileDependencies = 3, - AnonymousExecutableCount = 0; + AnonymousExecutableCount = 0; function Executable(/*String*/ aCode, /*Array*/ fileDependencies, /*CFURL|String*/ aURL, /*Function*/ aFunction, /*ObjJCompiler*/aCompiler, /*Dictionary*/ aFilenameTranslateDictionary, /* Base64 String */ sourceMap) { @@ -44,13 +43,7 @@ function Executable(/*String*/ aCode, /*Array*/ fileDependencies, /*CFURL|String if (sourceMap) this._base64EncodedSourceMap = sourceMap; - // This is a little hacky but if fileDependencies is null we can start loading file dependencies yet - if (!fileDependencies) - { - this._fileDependencyStatus = ExecutableCantStartLoadYetFileDependencies; - this._fileDependencyCallbacks = []; - } - else if (fileDependencies.length) + if (fileDependencies.length) { this._fileDependencyStatus = ExecutableUnloadedFileDependencies; this._fileDependencyCallbacks = []; @@ -188,9 +181,10 @@ Executable.prototype.execute = function() this.setCode(this._compiler.compilePass2(), this._compiler.map()); - if (FileExecutable.printWarningsAndErrors(this._compiler, exports.messageOutputFormatInXML)) + if (Executable.printWarningsAndErrors(this._compiler, exports.messageOutputFormatInXML)) throw "Compilation error"; + // We don't need to save the AST tree and the source code. It will take up a lot of memory. this._compiler = null; } @@ -314,8 +308,9 @@ Executable.prototype.loadFileDependencies = function(aCallback) if (status === ExecutableUnloadedFileDependencies) { - if (fileDependencyLoadCount) - throw "Can't load"; + if (fileDependencyLoadCount) { + throw "Can't load: " + this.URL().absoluteURL(); + } loadFileDependenciesForExecutable(this); } @@ -323,20 +318,12 @@ Executable.prototype.loadFileDependencies = function(aCallback) DISPLAY_NAME(Executable.prototype.loadFileDependencies); -Executable.prototype.setExecutableUnloadedFileDependencies = function() +Executable.prototype.hasExecutableUnloadedFileDependencies = function() { - if (this._fileDependencyStatus === ExecutableCantStartLoadYetFileDependencies) - this._fileDependencyStatus = ExecutableUnloadedFileDependencies; + return this._fileDependencyStatus === ExecutableUnloadedFileDependencies; } -DISPLAY_NAME(Executable.prototype.setExecutableUnloadedFileDependencies); - -Executable.prototype.isExecutableCantStartLoadYetFileDependencies = function() -{ - return this._fileDependencyStatus === ExecutableCantStartLoadYetFileDependencies; -} - -DISPLAY_NAME(Executable.prototype.setExecutableUnloadedFileDependencies); +DISPLAY_NAME(Executable.prototype.hasExecutableUnloadedFileDependencies); function loadFileDependenciesForExecutable(/*Executable*/ anExecutable) { @@ -442,6 +429,7 @@ DISPLAY_NAME(Executable.prototype.fileExecutableSearcher); var cachedFileExecuters = { }; +// All the file dependences must be loaded and executed before this can be executed. Executable.fileExecuterForURL = function(/*CFURL|String*/ aURL) { var referenceURL = makeAbsoluteURL(aURL), @@ -490,13 +478,13 @@ Executable.fileImporterForURL = function(/*CFURL|String*/ aURL) { aFileExecutable.loadFileDependencies(function() { - aFileExecutable.execute(); - + var result = aFileExecutable.execute(); + // No more need to cache these. disableCFURLCaching(); if (aCallback) - aCallback(); + aCallback(result); }); }); } @@ -512,16 +500,6 @@ DISPLAY_NAME(Executable.fileImporterForURL); var cachedFileExecutableSearchers = { }, cachedFileExecutableSearchResults = { }; -function countProp(x) { - var count = 0; - for (var k in x) { - if (x.hasOwnProperty(k)) { - ++count; - } - } - return count; -} - Executable.resetCachedFileExecutableSearchers = function() { cachedFileExecutableSearchers = { }; @@ -583,6 +561,53 @@ Executable.fileExecutableSearcherForURL = function(/*CFURL*/ referenceURL) DISPLAY_NAME(Executable.fileExecutableSearcherForURL); +/*! + This funtion prints all errors and warnings for the provided compiler. It returns true if there + are any errors in the list. it will print it in xml format if printXML is 'true' + */ +Executable.printWarningsAndErrors = function(/*ObjJCompiler*/ compiler, /*BOOL*/ printXML) +{ + var warnings = [], + anyErrors = false; + + for (var i = 0; i < compiler.warningsAndErrors.length; i++) + { + var warning = compiler.warningsAndErrors[i], + message = compiler.prettifyMessage(warning); + + // Set anyErrors to 'true' if there are any errors in the list + anyErrors = anyErrors || warning.messageType === "ERROR"; +#ifdef BROWSER + console.log(message); +#else + if (printXML) + { + var dict = new CFMutableDictionary(); + if (warning.messageOnLine != null) dict.addValueForKey('line', warning.messageOnLine) + if (warning.path != null) dict.addValueForKey('sourcePath', new CFURL(warning.path).path()) + if (message != null) dict.addValueForKey('message', message) + + warnings.push(dict); + } + else + { + print(message); + } +#endif + } + +#ifndef BROWSER + if (warnings.length && printXML) + try { + print(CFPropertyListCreateXMLData(warnings, kCFPropertyListXMLFormat_v1_0).rawString()); + } catch (e) { + print ("XML encode error: " + e); + } +#endif + + return anyErrors; +} + /* * Adaption to javascript by Malte Tancred 2012 from ConvertUTF.[ch] by Unicode, Inc. * Speed improvements by Martin Carlberg 2016 diff --git a/Objective-J/FileExecutable.js b/Objective-J/FileExecutable.js index 3b01c79fc..0513bc07f 100644 --- a/Objective-J/FileExecutable.js +++ b/Objective-J/FileExecutable.js @@ -22,10 +22,7 @@ var FileExecutablesForURLStrings = { }; -var currentCompilerFlags = {}; -var currentGccCompilerFlags = ""; - -function FileExecutable(/*CFURL|String*/ aURL, /*Dictionary*/ aFilenameTranslateDictionary) +function FileExecutable(/*CFURL|String*/ aURL, /*Dictionary*/ aFilenameTranslateDictionary, success) { aURL = makeAbsoluteURL(aURL); @@ -37,25 +34,14 @@ function FileExecutable(/*CFURL|String*/ aURL, /*Dictionary*/ aFilenameTranslate FileExecutablesForURLStrings[URLString] = this; - var fileContents = StaticResource.resourceAtURL(aURL).contents(), - executable = NULL, - extension = aURL.pathExtension().toLowerCase(); + var aResource = StaticResource.resourceAtURL(aURL), + fileContents = aResource.contents(), + executable = NULL; this._hasExecuted = NO; - if (fileContents.match(/^@STATIC;/)) - executable = decompile(fileContents, aURL); - else if ((extension === "j" || !extension) && !fileContents.match(/^{/)) - { - var compilerOptions = currentCompilerFlags || {}; - - this.cachedIncludeFileSearchResultsContent = {}; - this.cachedIncludeFileSearchResultsURL = {}; - compile(this, fileContents, aURL, compilerOptions, aFilenameTranslateDictionary); - return; - } - else - executable = new Executable(fileContents, [], aURL); + // Use code if resource contains code. If not use the content of the resource + executable = new Executable(fileContents, aResource._fileDependencies || [], aURL, aResource._function, aResource._compiler, aResource._compiler ? aFilenameTranslateDictionary : null, aResource._sourceMap); Executable.apply(this, [executable.code(), executable.fileDependencies(), aURL, executable._function, executable._compiler, aFilenameTranslateDictionary]); } @@ -64,143 +50,6 @@ exports.FileExecutable = FileExecutable; FileExecutable.prototype = new Executable(); -var compile = function(self, fileContents, aURL, compilerOptions, aFilenameTranslateDictionary) -{ - var acornOptions = compilerOptions.acornOptions || (compilerOptions.acornOptions = {}); - - acornOptions.preprocessGetIncludeFile = function(filePath, isQuoted) { - var referenceURL = new CFURL(".", aURL), // Remove the filename from the url - includeURL = new CFURL(filePath); - - var cacheUID = (isQuoted && referenceURL || "") + includeURL, - cachedResult = self.cachedIncludeFileSearchResultsContent[cacheUID]; - - if (!cachedResult) { - var isAbsoluteURL = (includeURL instanceof CFURL) && includeURL.scheme(), - compileWhenCompleted = NO; - - function completed(/*StaticResource*/ aStaticResource) { - var includeString = aStaticResource && aStaticResource.contents(), - lastCharacter = includeString && includeString.charCodeAt(includeString.length - 1); - - if (includeString == null) throw new Error("Can't load file " + includeURL); - // Add a new line if the last character is not. If the last thing is a '#define' of other preprocess - // token it will not be handled correctly if we don't have a end of line at the end. - if (lastCharacter !== 10 && lastCharacter !== 13 && lastCharacter !== 8232 && lastCharacter !== 8233) { - includeString += '\n'; - } - - self.cachedIncludeFileSearchResultsContent[cacheUID] = includeString; - self.cachedIncludeFileSearchResultsURL[cacheUID] = aStaticResource.URL(); - - if (compileWhenCompleted) - compile(self, fileContents, aURL, compilerOptions, aFilenameTranslateDictionary); - } - - if (isQuoted || isAbsoluteURL) - { - if (!isAbsoluteURL) - includeURL = new CFURL(includeURL, new CFURL((aFilenameTranslateDictionary[aURL.lastPathComponent()] || "."), referenceURL)); - - StaticResource.resolveResourceAtURL(includeURL, NO, completed); - } - else - StaticResource.resolveResourceAtURLSearchingIncludeURLs(includeURL, completed); - - // Now we try to get the cached result again. If we get it then the completed function has already - // executed and we can return the include dictionary. - cachedResult = self.cachedIncludeFileSearchResultsContent[cacheUID]; - } - - if (cachedResult) { - return {include: cachedResult, sourceFile: self.cachedIncludeFileSearchResultsURL[cacheUID]}; - } else { - // When the file is not available (resolved) return null to tell the parser to throw an exception to exit - // Also tell the completed function to compile when finished. - compileWhenCompleted = YES - return null; - } - }; - - var includeFiles = currentCompilerFlags && currentCompilerFlags.includeFiles, - allPreIncludesResolved = true; - - acornOptions.preIncludeFiles = []; - - if (includeFiles) for (var i = 0, size = includeFiles.length; i < size; i++) - { - var includeFileUrl = makeAbsoluteURL(includeFiles[i]); - - try - { - // try to get all pre include files that acorn will parse before the file from 'aURL' - var aResource = StaticResource.resourceAtURL(makeAbsoluteURL(includeFileUrl)); - } - catch (e) - { - // Ok, the file is not available (resolved). Resolve all of the files and try again when available. - StaticResource.resolveResourcesAtURLs(includeFiles.map(function(u) {return makeAbsoluteURL(u)}), function() { - compile(self, fileContents, aURL, compilerOptions, aFilenameTranslateDictionary); - }); - - allPreIncludesResolved = false; - break; - } - - if (aResource) - { - if (aResource.isNotFound()) { - throw new Error("--include file not found " + includeUrl); - } - - var includeString = aResource.contents(); - var lastCharacter = includeString.charCodeAt(includeString.length - 1); - - // Add a new line if the last character is not. If the last thing is a '#define' of other preprocess - // token it will not be handled correctly if we don't have a end of line at the end. - if (lastCharacter !== 10 && lastCharacter !== 13 && lastCharacter !== 8232 && lastCharacter !== 8233) - includeString += '\n'; - acornOptions.preIncludeFiles.push({include: includeString, sourceFile: includeFileUrl.toString()}); - } - } - - if (allPreIncludesResolved) - { - // '(exports.ObjJCompiler || ObjJCompiler)' is a temporary fix so it can work both in the Narwhal (exports.ObjJCompiler) and Node (ObjJCompiler) world - var compiler = (exports.ObjJCompiler || ObjJCompiler).compileFileDependencies(fileContents, aURL, compilerOptions); - var warningsAndErrors = compiler.warningsAndErrors; - - // Kind of a hack but if we get a file not found error on a #include the get include function above should have asked for the resource - // so we should be able to just bail out and wait for the the next call to compile when the include file is loaded (resolved) - if (warningsAndErrors && warningsAndErrors.length === 1 && warningsAndErrors[0].message.indexOf("file not found") > -1) - return; - - if (FileExecutable.printWarningsAndErrors(compiler, exports.messageOutputFormatInXML)) - throw "Compilation error"; - - var fileDependencies = compiler.dependencies.map(function (aFileDep) { - return new FileDependency(new CFURL(aFileDep.url), aFileDep.isLocal); - }); - } - - if (self.isExecutableCantStartLoadYetFileDependencies()) - { - // Include files that was not loaded has cancelled the compiler so we are already an initialized Executable. - // Just set the status so we can start loading the file dependencies. - self.setFileDependencies(fileDependencies); - self.setExecutableUnloadedFileDependencies(); - self.loadFileDependencies(); - } - else if (self._fileDependencyStatus == null) - { - // Are we still a FileExecutable. Call 'super' init method to make us a initilized subclass of an Executable. - executable = new Executable(compiler && compiler.jsBuffer ? compiler.jsBuffer.toString() : null, fileDependencies, aURL, null, compiler); - Executable.apply(self, [executable.code(), executable.fileDependencies(), aURL, executable._function, executable._compiler, aFilenameTranslateDictionary]); - } -} - -DISPLAY_NAME(compile); - #ifdef COMMONJS FileExecutable.allFileExecutables = function() { @@ -218,7 +67,6 @@ FileExecutable.allFileExecutables = function() FileExecutable.resetFileExecutables = function() { FileExecutablesForURLStrings = { }; - FunctionCache = { }; } FileExecutable.prototype.execute = function(/*BOOL*/ shouldForce) @@ -228,7 +76,7 @@ FileExecutable.prototype.execute = function(/*BOOL*/ shouldForce) this._hasExecuted = YES; - Executable.prototype.execute.call(this); + return Executable.prototype.execute.call(this); } DISPLAY_NAME(FileExecutable.prototype.execute); @@ -240,138 +88,3 @@ FileExecutable.prototype.hasExecuted = function() DISPLAY_NAME(FileExecutable.prototype.hasExecuted); -function decompile(/*String*/ aString, /*CFURL*/ aURL) -{ - var stream = new MarkedStream(aString); -/* - if (stream.version !== "1.0") - return; -*/ - var marker = NULL, - code = "", - dependencies = [], - sourceMap; - - while (marker = stream.getMarker()) - { - var text = stream.getString(); - - if (marker === MARKER_TEXT) - code += text; - - else if (marker === MARKER_IMPORT_STD) - dependencies.push(new FileDependency(new CFURL(text), NO)); - - else if (marker === MARKER_IMPORT_LOCAL) - dependencies.push(new FileDependency(new CFURL(text), YES)); - - else if (marker === MARKER_SOURCE_MAP) - sourceMap = text; - } - - var fn = FileExecutable._lookupCachedFunction(aURL); - - if (fn) - return new Executable(code, dependencies, aURL, fn, null, null, sourceMap); - - return new Executable(code, dependencies, aURL, null, null, null, sourceMap); -} - -var FunctionCache = { }; - -FileExecutable._cacheFunction = function(/*CFURL|String*/ aURL, /*Function*/ fn) -{ - aURL = typeof aURL === "string" ? aURL : aURL.absoluteString(); - FunctionCache[aURL] = fn; -} - -FileExecutable._lookupCachedFunction = function(/*CFURL|String*/ aURL) -{ - aURL = typeof aURL === "string" ? aURL : aURL.absoluteString(); - return FunctionCache[aURL]; -} - -FileExecutable.setCurrentGccCompilerFlags = function(/*String*/ compilerFlags) -{ - if (currentGccCompilerFlags === compilerFlags) return; - - currentGccCompilerFlags = compilerFlags; - - // '(exports.ObjJCompiler || ObjJCompiler)' is a temporary fix so it can work both in the Narwhal (exports.ObjJCompiler) and Node (ObjJCompiler) world - var objjcFlags = (exports.ObjJCompiler || ObjJCompiler).parseGccCompilerFlags(compilerFlags); - - FileExecutable.setCurrentCompilerFlags(objjcFlags); -} - -FileExecutable.currentGccCompilerFlags = function(/*String*/ compilerFlags) -{ - return currentGccCompilerFlags; -} - -FileExecutable.setCurrentCompilerFlags = function(/*JSObject*/ compilerFlags) -{ - currentCompilerFlags = compilerFlags; - // Here we set the default flags if they are not included. We do this as the default values - // in the compiler might not be what we want. - if (currentCompilerFlags.transformNamedFunctionDeclarationToAssignment == null) - currentCompilerFlags.transformNamedFunctionDeclarationToAssignment = true; - if (currentCompilerFlags.sourceMap == null) - currentCompilerFlags.sourceMap = false; - if (currentCompilerFlags.inlineMsgSendFunctions == null) - currentCompilerFlags.inlineMsgSendFunctions = false; -} - -FileExecutable.currentCompilerFlags = function(/*JSObject*/ compilerFlags) -{ - return currentCompilerFlags; -} - -/*! - This funtion prints all errors and warnings for the provieded compiler. It returns true if there - are any errors in the list. it will print it in xml format if printXML is 'true' - */ -FileExecutable.printWarningsAndErrors = function(/*ObjJCompiler*/ compiler, /*BOOL*/ printXML) -{ - var warnings = [], - anyErrors = false; - - for (var i = 0; i < compiler.warningsAndErrors.length; i++) - { - var warning = compiler.warningsAndErrors[i], - message = compiler.prettifyMessage(warning); - - // Set anyErrors to 'true' if there are any errors in the list - anyErrors = anyErrors || warning.messageType === "ERROR"; -#ifdef BROWSER - console.log(message); -#else - if (printXML) - { - var dict = new CFMutableDictionary(); - if (warning.messageOnLine != null) dict.addValueForKey('line', warning.messageOnLine) - if (warning.path != null) dict.addValueForKey('sourcePath', new CFURL(warning.path).path()) - if (message != null) dict.addValueForKey('message', message) - - warnings.push(dict); - } - else - { - print(message); - } -#endif - } - -#ifndef BROWSER - if (warnings.length && printXML) - try { - print(CFPropertyListCreateXMLData(warnings, kCFPropertyListXMLFormat_v1_0).rawString()); - } catch (e) { - print ("XML encode error: " + e); - } -#endif - - return anyErrors; -} - -// Set the compiler flags to empty dictionary so the default values are correct. -FileExecutable.setCurrentCompilerFlags({}); diff --git a/Objective-J/OldBrowserCompatibility.js b/Objective-J/OldBrowserCompatibility.js index 71a917063..285f5c175 100644 --- a/Objective-J/OldBrowserCompatibility.js +++ b/Objective-J/OldBrowserCompatibility.js @@ -280,3 +280,34 @@ if (!Array.prototype.find) { writable: true }); } + +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign +if (typeof Object.assign !== 'function') { + // Must be writable: true, enumerable: false, configurable: true + Object.defineProperty(Object, "assign", { + value: function assign(target, varArgs) { // .length of function is 2 + 'use strict'; + if (target === null || target === undefined) { + throw new TypeError('Cannot convert undefined or null to object'); + } + + var to = Object(target); + + for (var index = 1; index < arguments.length; index++) { + var nextSource = arguments[index]; + + if (nextSource !== null && nextSource !== undefined) { + for (var nextKey in nextSource) { + // Avoid bugs when hasOwnProperty is shadowed + if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) { + to[nextKey] = nextSource[nextKey]; + } + } + } + } + return to; + }, + writable: true, + configurable: true + }); +} diff --git a/Objective-J/StaticResource.js b/Objective-J/StaticResource.js index 2a4d68c2b..be73e86af 100644 --- a/Objective-J/StaticResource.js +++ b/Objective-J/StaticResource.js @@ -1,6 +1,9 @@ var rootResources = { }; +var currentCompilerFlags = {}; +var currentGccCompilerFlags = ""; + function StaticResource(/*CFURL*/ aURL, /*StaticResource*/ aParent, /*BOOL*/ isDirectory, /*BOOL*/ isResolved, /*Dictionary*/ aFilenameTranslateDictionary) { this._parent = aParent; @@ -37,19 +40,10 @@ StaticResource.rootResources = function() return rootResources; }; -function countProp(x) { - var count = 0; - for (var k in x) { - if (x.hasOwnProperty(k)) { - ++count; - } - } - return count; -} - StaticResource.resetRootResources = function() { rootResources = {}; + FunctionCache = {}; }; StaticResource.prototype.filenameTranslateDictionary = function() @@ -69,7 +63,7 @@ function resolveStaticResource(/*StaticResource*/ aResource) }); } -StaticResource.prototype.resolve = function() +StaticResource.prototype.resolve = function(/*BOOL*/ dontCompile, /*Array*/ compileIncludeFileArray) { if (this.isDirectory()) { @@ -87,8 +81,41 @@ StaticResource.prototype.resolve = function() function onsuccess(/*anEvent*/ anEvent) { - self._contents = anEvent.request.responseText(); - resolveStaticResource(self); + var fileContents = anEvent.request.responseText(), + aURL = self.URL(), + extension = aURL.pathExtension().toLowerCase(); + + self._contents = fileContents; + + if (fileContents.match(/^@STATIC;/)) + { + self.decompile(); + resolveStaticResource(self); + } + else if (!dontCompile && (extension === "j" || !extension) && !fileContents.match(/^{/)) + { + // Copy compiler options as this can be recursive and/or asynchronous. + // Specially acornOptions.preprocessGetIncludeFile that has a variable 'self' that needs to be referencing the resource. + var compilerOptions = Object.assign({}, currentCompilerFlags || {}), + acornOptions = compilerOptions.acornOptions; + + if (acornOptions) + compilerOptions.acornOptions = Object.asign({}, acornOptions); + + // If no include files are set use the include files from the bundle, if any. + if (!compilerOptions.includeFiles) + compilerOptions.includeFiles = compileIncludeFileArray; + + self.cachedIncludeFileSearchResultsContent = {}; + self.cachedIncludeFileSearchResultsURL = {}; + compile(self, fileContents, aURL, compilerOptions, aFilenameTranslateDictionary, function(aResource) { + resolveStaticResource(aResource); + }); + } + else + { + resolveStaticResource(self); + } } function onfailure() @@ -114,6 +141,221 @@ StaticResource.prototype.resolve = function() } }; +var compile = function(self, fileContents, aURL, compilerOptions, aFilenameTranslateDictionary, success) +{ + var acornOptions = compilerOptions.acornOptions || (compilerOptions.acornOptions = {}); + + acornOptions.preprocessGetIncludeFile = function(filePath, isQuoted) { + var referenceURL = new CFURL(".", aURL), // Remove the filename from the url + includeURL = new CFURL(filePath); + + var cacheUID = (isQuoted && referenceURL || "") + includeURL, + cachedResult = self.cachedIncludeFileSearchResultsContent[cacheUID]; + + if (!cachedResult) { + var isAbsoluteURL = (includeURL instanceof CFURL) && includeURL.scheme(), + compileWhenCompleted = NO; + + function completed(/*StaticResource*/ aStaticResource) { + var includeString = aStaticResource && aStaticResource.contents(), + lastCharacter = includeString && includeString.charCodeAt(includeString.length - 1); + + if (includeString == null) throw new Error("Can't load file " + includeURL); + // Add a new line if the last character is not. If the last thing is a '#define' of other preprocess + // token it will not be handled correctly if we don't have a end of line at the end. + if (lastCharacter !== 10 && lastCharacter !== 13 && lastCharacter !== 8232 && lastCharacter !== 8233) { + includeString += '\n'; + } + + self.cachedIncludeFileSearchResultsContent[cacheUID] = includeString; + self.cachedIncludeFileSearchResultsURL[cacheUID] = aStaticResource.URL(); + + if (compileWhenCompleted) + compile(self, fileContents, aURL, compilerOptions, aFilenameTranslateDictionary, success); + } + + if (isQuoted || isAbsoluteURL) + { + var translateDictionary; + + if (!isAbsoluteURL) { + includeURL = new CFURL(includeURL, new CFURL(((aFilenameTranslateDictionary && aFilenameTranslateDictionary[aURL.lastPathComponent()]) || "."), referenceURL)); + } + + StaticResource.resolveResourceAtURL(includeURL, NO, completed, null, true); // true = don't compile any loaded resource + } + else + StaticResource.resolveResourceAtURLSearchingIncludeURLs(includeURL, completed); + + // Now we try to get the cached result again. If we get it then the completed function has already + // executed and we can return the include dictionary. + cachedResult = self.cachedIncludeFileSearchResultsContent[cacheUID]; + } + + if (cachedResult) { + return {include: cachedResult, sourceFile: self.cachedIncludeFileSearchResultsURL[cacheUID]}; + } else { + // When the file is not available (resolved) return null to tell the parser to throw an exception to exit + // Also tell the completed function to compile when finished as it has not yet done so. + // If fetching the resources are synchronous the result will be found above and the completion function + // should not compile again. + compileWhenCompleted = YES; + return null; + } + }; + + var includeFiles = compilerOptions && compilerOptions.includeFiles, + allPreIncludesResolved = true; + + acornOptions.preIncludeFiles = []; + + if (includeFiles) for (var i = 0, size = includeFiles.length; i < size; i++) + { + var includeFileUrl = makeAbsoluteURL(includeFiles[i]); + + try + { + // try to get all pre include files that acorn will parse before the file from 'aURL' + var aResource = StaticResource.resourceAtURL(makeAbsoluteURL(includeFileUrl)); + } + catch (e) + { + // Ok, the file is not available (resolved). Resolve all of the files and try again when available. + StaticResource.resolveResourcesAtURLs(includeFiles.map(function(u) {return makeAbsoluteURL(u)}), function() { + compile(self, fileContents, aURL, compilerOptions, aFilenameTranslateDictionary, success); + }); + + // Now we need to bail out as the compile completion function has already been + // called (synchronous) or will be called in the future (asynchronous) + return; + } + + if (aResource) + { + if (aResource.isNotFound()) { + throw new Error("--include file not found " + includeUrl); + } + + var includeString = aResource.contents(); + var lastCharacter = includeString.charCodeAt(includeString.length - 1); + + // Add a new line if the last character is not. If the last thing is a '#define' of other preprocess + // token it will not be handled correctly if we don't have a end of line at the end. + if (lastCharacter !== 10 && lastCharacter !== 13 && lastCharacter !== 8232 && lastCharacter !== 8233) + includeString += '\n'; + acornOptions.preIncludeFiles.push({include: includeString, sourceFile: includeFileUrl.toString()}); + } + } + + // '(exports.ObjJCompiler || ObjJCompiler)' is a temporary fix so it can work both in the Narwhal (exports.ObjJCompiler) and Node (ObjJCompiler) world + var compiler = (exports.ObjJCompiler || ObjJCompiler).compileFileDependencies(fileContents, aURL, compilerOptions); + var warningsAndErrors = compiler.warningsAndErrors; + + // Kind of a hack but if we get a file not found error on a #include the get include function above should have asked for the resource + // so we should be able to just bail out and wait for the the next call to compile when the include file is loaded (resolved) + if (warningsAndErrors && warningsAndErrors.length === 1 && warningsAndErrors[0].message.indexOf("file not found") > -1) + return; + + if (Executable.printWarningsAndErrors(compiler, exports.messageOutputFormatInXML)) { + throw "Compilation error"; + } + + var fileDependencies = compiler.dependencies.map(function (aFileDep) { + return new FileDependency(new CFURL(aFileDep.url), aFileDep.isLocal); + }); + + self._fileDependencies = fileDependencies; + self._compiler = compiler; + + success(self); +} + +StaticResource.prototype.decompile = function() +{ + var content = this.contents(), + aURL = this.URL(), + stream = new MarkedStream(content); +/* + if (stream.version !== "1.0") + return; +*/ + var marker = NULL, + code = "", + dependencies = [], + sourceMap; + + while (marker = stream.getMarker()) + { + var text = stream.getString(); + + if (marker === MARKER_TEXT) + code += text; + + else if (marker === MARKER_IMPORT_STD) + dependencies.push(new FileDependency(new CFURL(text), NO)); + + else if (marker === MARKER_IMPORT_LOCAL) + dependencies.push(new FileDependency(new CFURL(text), YES)); + + else if (marker === MARKER_SOURCE_MAP) + sourceMap = text; + } + + this._fileDependencies = dependencies; + this._function = StaticResource._lookupCachedFunction(aURL); + this._sourceMap = sourceMap; + this._contents = code; +} + +StaticResource.setCurrentGccCompilerFlags = function(/*String*/ compilerFlags) +{ + if (currentGccCompilerFlags === compilerFlags) return; + + currentGccCompilerFlags = compilerFlags; + + // '(exports.ObjJCompiler || ObjJCompiler)' is a temporary fix so it can work both in the Narwhal (exports.ObjJCompiler) and Node (ObjJCompiler) world + var objjcFlags = (exports.ObjJCompiler || ObjJCompiler).parseGccCompilerFlags(compilerFlags); + + StaticResource.setCurrentCompilerFlags(objjcFlags); +} + +StaticResource.currentGccCompilerFlags = function(/*String*/ compilerFlags) +{ + return currentGccCompilerFlags; +} + +StaticResource.setCurrentCompilerFlags = function(/*JSObject*/ compilerFlags) +{ + currentCompilerFlags = compilerFlags; + // Here we set the default flags if they are not included. We do this as the default values + // in the compiler might not be what we want. + if (currentCompilerFlags.transformNamedFunctionDeclarationToAssignment == null) + currentCompilerFlags.transformNamedFunctionDeclarationToAssignment = true; + if (currentCompilerFlags.sourceMap == null) + currentCompilerFlags.sourceMap = false; + if (currentCompilerFlags.inlineMsgSendFunctions == null) + currentCompilerFlags.inlineMsgSendFunctions = false; +} + +StaticResource.currentCompilerFlags = function(/*JSObject*/ compilerFlags) +{ + return currentCompilerFlags; +} + +var FunctionCache = { }; + +StaticResource._cacheFunction = function(/*CFURL|String*/ aURL, /*Function*/ fn) +{ + aURL = typeof aURL === "string" ? aURL : aURL.absoluteString(); + FunctionCache[aURL] = fn; +} + +StaticResource._lookupCachedFunction = function(/*CFURL|String*/ aURL) +{ + aURL = typeof aURL === "string" ? aURL : aURL.absoluteString(); + return FunctionCache[aURL]; +} + StaticResource.prototype.name = function() { return this._name; @@ -218,11 +460,11 @@ StaticResource.resolveResourcesAtURLs = function(/*Array of CFURL|String*/ URLs, } } -StaticResource.resolveResourceAtURL = function(/*CFURL|String*/ aURL, /*BOOL*/ isDirectory, /*Function*/ aCallback, /*Dictionary*/ aFilenameTranslateDictionary) +StaticResource.resolveResourceAtURL = function(/*CFURL|String*/ aURL, /*BOOL*/ isDirectory, /*Function*/ aCallback, /*Dictionary*/ aFilenameTranslateDictionary, /*BOOL*/ dontCompile) { aURL = makeAbsoluteURL(aURL).absoluteURL(); - resolveResourceComponents(rootResourceForAbsoluteURL(aURL), isDirectory, aURL.pathComponents(), 0, aCallback, aFilenameTranslateDictionary); + resolveResourceComponents(rootResourceForAbsoluteURL(aURL), isDirectory, aURL.pathComponents(), 0, aCallback, aFilenameTranslateDictionary, null, dontCompile); }; StaticResource.prototype.resolveResourceAtURL = function(/*CFURL|String*/ aURL, /*BOOL*/ isDirectory, /*Function*/ aCallback) @@ -230,7 +472,7 @@ StaticResource.prototype.resolveResourceAtURL = function(/*CFURL|String*/ aURL, StaticResource.resolveResourceAtURL(new CFURL(aURL, this.URL()).absoluteURL(), isDirectory, aCallback); }; -function resolveResourceComponents(/*StaticResource*/ aResource, /*BOOL*/ isDirectory, /*Array*/ components, /*Integer*/ index, /*Function*/ aCallback, /*Dictionry*/ aFilenameTranslateDictionary) +function resolveResourceComponents(/*StaticResource*/ aResource, /*BOOL*/ isDirectory, /*Array*/ components, /*Integer*/ index, /*Function*/ aCallback, /*Dictionary*/ aFilenameTranslateDictionary, /*Array*/ compileIncludeFileArray, /*BOOL*/ dontCompile) { var count = components.length; @@ -242,8 +484,31 @@ function resolveResourceComponents(/*StaticResource*/ aResource, /*BOOL*/ isDire // If the child doesn't exist, create and resolve it. if (!child) { - child = new StaticResource(new CFURL(name, aResource.URL()), aResource, index + 1 < count || isDirectory , NO, aFilenameTranslateDictionary); - child.resolve(); + var translationDictionary = nil; + if (aFilenameTranslateDictionary == null) { + var bundle = new CFBundle(aResource.URL()); + + if (bundle != null) { + var bundleTranslationDictionary = bundle.valueForInfoDictionaryKey("CPFileTranslationDictionary"); + + if (bundleTranslationDictionary != null) { + translationDictionary = bundleTranslationDictionary.toJSObject(); + } + + var bundleIncludeFileArray = bundle.valueForInfoDictionaryKey("CPCompileIncludeFileArray"); + + if (bundleIncludeFileArray != null) { + compileIncludeFileArray = bundleIncludeFileArray.map(function(includeFilePath) { + return new CFURL(includeFilePath, aResource.URL()); + }); + } + } + } + + var u = new CFURL(name, aResource.URL()); + + child = new StaticResource(u, aResource, index + 1 < count || isDirectory , NO, translationDictionary || aFilenameTranslateDictionary); + child.resolve(dontCompile, compileIncludeFileArray); } // If this resource is still being resolved, just wait and rerun this same method when it's ready. @@ -251,7 +516,7 @@ function resolveResourceComponents(/*StaticResource*/ aResource, /*BOOL*/ isDire return child.addEventListener("resolve", function() { // Continue resolving once this is done. - resolveResourceComponents(aResource, isDirectory, components, index, aCallback, aFilenameTranslateDictionary); + resolveResourceComponents(aResource, isDirectory, components, index, aCallback, aFilenameTranslateDictionary, compileIncludeFileArray, dontCompile); }); // If we've already determined that this file doesn't exist... @@ -364,3 +629,6 @@ StaticResource.includeURLs = function() return includeURLs; }; + +// Set the compiler flags to empty dictionary so the default values are correct. +StaticResource.setCurrentCompilerFlags({});