diff --git a/.gitmodules b/.gitmodules index e137d593d..b51caec4c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -43,6 +43,3 @@ [submodule "vendor/haskell-tree-sitter"] path = vendor/haskell-tree-sitter url = https://github.com/tree-sitter/haskell-tree-sitter.git -[submodule "test/corpus/profile"] - path = test/corpus/profile - url = https://github.com/diff-fixtures/profile.git diff --git a/semantic-diff.cabal b/semantic-diff.cabal index cf84bfc64..342865206 100644 --- a/semantic-diff.cabal +++ b/semantic-diff.cabal @@ -140,7 +140,6 @@ test-suite test hs-source-dirs: test main-is: Spec.hs other-modules: AlignmentSpec - , CorpusSpec , Data.Mergeable.Spec , Data.RandomWalkSimilarity.Spec , Diff.Spec diff --git a/test/CorpusSpec.hs b/test/CorpusSpec.hs deleted file mode 100644 index c8c18c566..000000000 --- a/test/CorpusSpec.hs +++ /dev/null @@ -1,101 +0,0 @@ -{-# LANGUAGE DataKinds, FlexibleContexts, GeneralizedNewtypeDeriving #-} -module CorpusSpec where - -import Category -import Control.DeepSeq -import Data.Functor.Both -import Data.List (union) -import Data.Record -import qualified Data.Text as T -import Diffing -import GHC.Show (Show(..)) -import Info -import Prologue hiding (fst, snd, lookup) -import Parse -import Renderer -import qualified Renderer.JSON as J -import qualified Renderer.Patch as P -import qualified Renderer.Split as Split -import qualified Source as S -import System.FilePath -import System.FilePath.Glob -import Test.Hspec (Spec, describe, it, SpecWith, runIO, parallel) -import Test.Hspec.Expectations.Pretty -import Unsafe (unsafeFromJust) - -spec :: Spec -spec = parallel $ do - describe "crashers crash" . runTestsIn "test/crashers-todo/" $ \ a b -> - a `deepseq` pure (a == b) `shouldThrow` anyException - describe "crashers should not crash" $ runTestsIn "test/crashers/" shouldBe - describe "todos are incorrect" $ runTestsIn "test/diffs-todo/" shouldNotBe - describe "should produce the correct diff" $ runTestsIn "test/diffs/" shouldBe - - it "lists example fixtures" $ do - examples "test/crashers/" `shouldNotReturn` [] - examples "test/diffs/" `shouldNotReturn` [] - - where - runTestsIn :: FilePath -> (Maybe Verbatim -> Maybe Verbatim -> Expectation) -> SpecWith () - runTestsIn directory matcher = do - paths <- runIO $ examples directory - let tests = correctTests =<< paths - traverse_ (\ (formatName, renderer, paths, output) -> - it (maybe "/dev/null" normalizeName (uncurry (<|>) (runJoin paths)) ++ " (" ++ formatName ++ ")") $ testDiff renderer paths output matcher) tests - - correctTests paths@(_, _, Nothing, Nothing, Nothing) = testsForPaths paths - correctTests paths = filter (\(_, _, _, output) -> isJust output) $ testsForPaths paths - testsForPaths (aPath, bPath, json, patch, split) = [ ("json", J.json, paths, json), ("patch", P.patch, paths, patch), ("split", Split.split, paths, split) ] - where paths = both aPath bPath - --- | Return all the examples from the given directory. Examples are expected to --- | have the form "foo.A.js", "foo.B.js", "foo.patch.js". Diffs are not --- | required as the test may be verifying that the inputs don't crash. -examples :: FilePath -> IO [(Maybe FilePath, Maybe FilePath, Maybe FilePath, Maybe FilePath, Maybe FilePath)] -examples directory = do - as <- globFor "*.A.*" - bs <- globFor "*.B.*" - jsons <- globFor "*.json.*" - patches <- globFor "*.patch.*" - splits <- globFor "*.split.*" - - let lookupName name = (lookupNormalized name as, lookupNormalized name bs, lookupNormalized name jsons, lookupNormalized name patches, lookupNormalized name splits) - - let keys = (normalizeName <$> as) `union` (normalizeName <$> bs) - pure $ lookupName <$> keys - where - lookupNormalized name = find $ (== name) . normalizeName - globFor :: FilePath -> IO [FilePath] - globFor p = globDir1 (compile p) directory - --- | Given a test name like "foo.A.js", return "foo.js". -normalizeName :: FilePath -> FilePath -normalizeName path = addExtension (dropExtension $ dropExtension path) (takeExtension path) - --- | Given file paths for A, B, and, optionally, a diff, return whether diffing --- | the files will produce the diff. If no diff is provided, then the result --- | is true, but the diff will still be calculated. -testDiff :: Renderer (Record '[Range, Category, SourceSpan]) -> Both (Maybe FilePath) -> Maybe FilePath -> (Maybe Verbatim -> Maybe Verbatim -> Expectation) -> Expectation -testDiff renderer paths diff matcher = do - sources <- traverse (traverse readAndTranscodeFile) paths - actual <- fmap Verbatim <$> traverse ((pure . concatOutputs . pure) <=< diffFiles' sources) parser - case diff of - Nothing -> matcher actual actual - Just file -> do - expected <- Verbatim <$> readFile file - matcher actual (Just expected) - where diffFiles' sources parser = diffFiles parser renderer (sourceBlobs sources paths) - parser = parserForFilepath <$> runBothWith (<|>) paths - sourceBlobs :: Both (Maybe (S.Source)) -> Both (Maybe FilePath) -> Both S.SourceBlob - sourceBlobs sources paths = case runJoin paths of - (Nothing, Nothing) -> Join (S.emptySourceBlob "", S.emptySourceBlob "") - (Nothing, Just filepath) -> Join (S.emptySourceBlob "", S.sourceBlob (unsafeFromJust $ snd sources) filepath) - (Just filepath, Nothing) -> Join (S.sourceBlob (unsafeFromJust $ fst sources) filepath, S.emptySourceBlob "") - (Just path1, Just path2) -> Join (S.sourceBlob (unsafeFromJust $ fst sources) path1, S.sourceBlob (unsafeFromJust $ snd sources) path2) - --- | A wrapper around `Text` with a more readable `Show` instance. -newtype Verbatim = Verbatim Text - deriving (Eq, NFData) - -instance Show Verbatim where - showsPrec _ (Verbatim text) = ('\n':) . (T.unpack text ++) diff --git a/test/Spec.hs b/test/Spec.hs index 9bb92ce95..bff861fdc 100644 --- a/test/Spec.hs +++ b/test/Spec.hs @@ -2,7 +2,6 @@ module Main where import Prologue import qualified AlignmentSpec -import qualified CorpusSpec import qualified Data.Mergeable.Spec import qualified Data.RandomWalkSimilarity.Spec import qualified Diff.Spec @@ -19,7 +18,6 @@ import Test.Hspec main :: IO () main = hspec . parallel $ do describe "Alignment" AlignmentSpec.spec - describe "Corpus" CorpusSpec.spec describe "Data.Mergeable" Data.Mergeable.Spec.spec describe "Data.RandomWalkSimilarity" Data.RandomWalkSimilarity.Spec.spec describe "Diff.Spec" Diff.Spec.spec diff --git a/test/corpus/profile b/test/corpus/profile deleted file mode 160000 index 0abfd2c8b..000000000 --- a/test/corpus/profile +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 0abfd2c8bbb78433b6a3d297a00c0bc302040829 diff --git a/test/crashers/433-1.A.js b/test/crashers/433-1.A.js deleted file mode 100644 index 3bc9f5be3..000000000 --- a/test/crashers/433-1.A.js +++ /dev/null @@ -1,4 +0,0 @@ -{ - // g - a: 5 -} diff --git a/test/crashers/433-1.B.js b/test/crashers/433-1.B.js deleted file mode 100644 index b28b42feb..000000000 --- a/test/crashers/433-1.B.js +++ /dev/null @@ -1,4 +0,0 @@ -{ - // G - a: 5 -} diff --git a/test/crashers/433-2.A.js b/test/crashers/433-2.A.js deleted file mode 100644 index c3c4430f9..000000000 --- a/test/crashers/433-2.A.js +++ /dev/null @@ -1,3 +0,0 @@ -{ - a: 5 -} diff --git a/test/crashers/433-2.B.js b/test/crashers/433-2.B.js deleted file mode 100644 index 4ae5684bc..000000000 --- a/test/crashers/433-2.B.js +++ /dev/null @@ -1,4 +0,0 @@ -{ - c: 4, - a: 5 -} diff --git a/test/crashers/440.A.js b/test/crashers/440.A.js deleted file mode 100644 index d464cd7ac..000000000 --- a/test/crashers/440.A.js +++ /dev/null @@ -1,4 +0,0 @@ -{ - "b": 4, - "a": 5 -} diff --git a/test/crashers/440.B.js b/test/crashers/440.B.js deleted file mode 100644 index 7c227494b..000000000 --- a/test/crashers/440.B.js +++ /dev/null @@ -1,4 +0,0 @@ -{ - "b": 5, - "a": 5 -} diff --git a/test/crashers/488.A.js b/test/crashers/488.A.js deleted file mode 100644 index 8533bdc41..000000000 --- a/test/crashers/488.A.js +++ /dev/null @@ -1,4 +0,0 @@ -{ - a: 1, - b: 1 -} diff --git a/test/crashers/488.B.js b/test/crashers/488.B.js deleted file mode 100644 index 0608057b5..000000000 --- a/test/crashers/488.B.js +++ /dev/null @@ -1,4 +0,0 @@ -{ - b: 1, - a: 1 -} diff --git a/test/crashers/573.A.js b/test/crashers/573.A.js deleted file mode 100644 index 013a570e0..000000000 --- a/test/crashers/573.A.js +++ /dev/null @@ -1,2 +0,0 @@ -if (a && - b) {} diff --git a/test/crashers/573.B.js b/test/crashers/573.B.js deleted file mode 100644 index c9e37d4c8..000000000 --- a/test/crashers/573.B.js +++ /dev/null @@ -1 +0,0 @@ -if (a && b) {} diff --git a/test/diffs/asymmetrical-context.A.js b/test/diffs/asymmetrical-context.A.js deleted file mode 100644 index cc26b9ec3..000000000 --- a/test/diffs/asymmetrical-context.A.js +++ /dev/null @@ -1,2 +0,0 @@ -console.log('hello'); -console.log('world'); diff --git a/test/diffs/asymmetrical-context.B.js b/test/diffs/asymmetrical-context.B.js deleted file mode 100644 index 904cb60ce..000000000 --- a/test/diffs/asymmetrical-context.B.js +++ /dev/null @@ -1,6 +0,0 @@ -console.log('hello'); - - - - -console.log('world'); diff --git a/test/diffs/asymmetrical-context.split.js b/test/diffs/asymmetrical-context.split.js deleted file mode 100644 index 4bdc27d55..000000000 --- a/test/diffs/asymmetrical-context.split.js +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - -
1
      • console
      • .
      • log
      • (
      • 'hello'
      • )
    • ;
  • -
1
      • console
      • .
      • log
      • (
      • 'hello'
      • )
    • ;
  • -
2
    -
3
    -
4
    -
5
    -
2
      • console
      • .
      • log
      • (
      • 'world'
      • )
    • ;
  • -
6
      • console
      • .
      • log
      • (
      • 'world'
      • )
    • ;
  • -
3
    7
      \ No newline at end of file diff --git a/test/diffs/dictionary.A.js b/test/diffs/dictionary.A.js deleted file mode 100644 index d464cd7ac..000000000 --- a/test/diffs/dictionary.A.js +++ /dev/null @@ -1,4 +0,0 @@ -{ - "b": 4, - "a": 5 -} diff --git a/test/diffs/dictionary.B.js b/test/diffs/dictionary.B.js deleted file mode 100644 index 7c227494b..000000000 --- a/test/diffs/dictionary.B.js +++ /dev/null @@ -1,4 +0,0 @@ -{ - "b": 5, - "a": 5 -} diff --git a/test/diffs/dictionary.json.js b/test/diffs/dictionary.json.js deleted file mode 100644 index 851fb9973..000000000 --- a/test/diffs/dictionary.json.js +++ /dev/null @@ -1 +0,0 @@ -{"oids":["0000000000000000000000000000000000000000","0000000000000000000000000000000000000000"],"paths":["test/diffs/dictionary.A.js","test/diffs/dictionary.B.js"],"rows":[[{"terms":[{"category":"Program","children":[{"category":"ExpressionStatements","children":[{"category":"Object","children":[],"range":[0,2]}],"range":[0,2]}],"range":[0,2]}],"hasChanges":false,"range":[0,2],"number":1},{"terms":[{"category":"Program","children":[{"category":"ExpressionStatements","children":[{"category":"Object","children":[],"range":[0,2]}],"range":[0,2]}],"range":[0,2]}],"hasChanges":false,"range":[0,2],"number":1}],[{"terms":[{"category":"Program","children":[{"category":"ExpressionStatements","children":[{"category":"Object","children":[{"category":"Pair","children":[{"category":"StringLiteral","range":[4,7]},{"category":"NumberLiteral","patch":"replace","range":[9,10]}],"range":[4,10]}],"range":[2,12]}],"range":[2,12]}],"range":[2,12]}],"hasChanges":true,"range":[2,12],"number":2},{"terms":[{"category":"Program","children":[{"category":"ExpressionStatements","children":[{"category":"Object","children":[{"category":"Pair","children":[{"category":"StringLiteral","range":[4,7]},{"category":"NumberLiteral","patch":"replace","range":[9,10]}],"range":[4,10]}],"range":[2,12]}],"range":[2,12]}],"range":[2,12]}],"hasChanges":true,"range":[2,12],"number":2}],[{"terms":[{"category":"Program","children":[{"category":"ExpressionStatements","children":[{"category":"Object","children":[{"category":"Pair","children":[{"category":"StringLiteral","range":[14,17]},{"category":"NumberLiteral","range":[19,20]}],"range":[14,20]}],"range":[12,21]}],"range":[12,21]}],"range":[12,21]}],"hasChanges":false,"range":[12,21],"number":3},{"terms":[{"category":"Program","children":[{"category":"ExpressionStatements","children":[{"category":"Object","children":[{"category":"Pair","children":[{"category":"StringLiteral","range":[14,17]},{"category":"NumberLiteral","range":[19,20]}],"range":[14,20]}],"range":[12,21]}],"range":[12,21]}],"range":[12,21]}],"hasChanges":false,"range":[12,21],"number":3}],[{"terms":[{"category":"Program","children":[{"category":"ExpressionStatements","children":[{"category":"Object","children":[],"range":[21,22]}],"range":[21,23]}],"range":[21,23]}],"hasChanges":false,"range":[21,23],"number":4},{"terms":[{"category":"Program","children":[{"category":"ExpressionStatements","children":[{"category":"Object","children":[],"range":[21,22]}],"range":[21,23]}],"range":[21,23]}],"hasChanges":false,"range":[21,23],"number":4}],[{"terms":[{"category":"Program","children":[],"range":[23,23]}],"hasChanges":false,"range":[23,23],"number":5},{"terms":[{"category":"Program","children":[],"range":[23,23]}],"hasChanges":false,"range":[23,23],"number":5}]]} \ No newline at end of file diff --git a/test/diffs/dictionary.patch.js b/test/diffs/dictionary.patch.js deleted file mode 100644 index 49351e5ae..000000000 --- a/test/diffs/dictionary.patch.js +++ /dev/null @@ -1,10 +0,0 @@ -diff --git a/test/diffs/dictionary.A.js b/test/diffs/dictionary.B.js -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/test/diffs/dictionary.A.js -+++ b/test/diffs/dictionary.B.js -@@ -1,5 +1,5 @@ - { -- "b": 4, -+ "b": 5, - "a": 5 - } diff --git a/test/diffs/dictionary.split.js b/test/diffs/dictionary.split.js deleted file mode 100644 index 698982c5b..000000000 --- a/test/diffs/dictionary.split.js +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - -
      1
          • { -
      1
          • { -
      2
            • "b"
            • :
            • 4
          • , -
      2
            • "b"
            • :
            • 5
          • , -
      3
            • "a"
            • :
            • 5
          • -
      3
            • "a"
            • :
            • 5
          • -
      4
          • }
        • -
      4
          • }
        • -
      5
        5
          \ No newline at end of file diff --git a/test/diffs/file-addition.B.js b/test/diffs/file-addition.B.js deleted file mode 100644 index e69de29bb..000000000 diff --git a/test/diffs/file-addition.patch.js b/test/diffs/file-addition.patch.js deleted file mode 100644 index 6c04a8f0f..000000000 --- a/test/diffs/file-addition.patch.js +++ /dev/null @@ -1,3 +0,0 @@ -diff --git a/test/diffs/file-addition.B.js b/test/diffs/file-addition.B.js -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 diff --git a/test/diffs/file-deletion.A.js b/test/diffs/file-deletion.A.js deleted file mode 100644 index e69de29bb..000000000 diff --git a/test/diffs/file-deletion.patch.js b/test/diffs/file-deletion.patch.js deleted file mode 100644 index dea2c8982..000000000 --- a/test/diffs/file-deletion.patch.js +++ /dev/null @@ -1,3 +0,0 @@ -diff --git a/test/diffs/file-deletion.A.js b/test/diffs/file-deletion.A.js -deleted file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 diff --git a/test/diffs/insert.A.js b/test/diffs/insert.A.js deleted file mode 100644 index e921523b1..000000000 --- a/test/diffs/insert.A.js +++ /dev/null @@ -1 +0,0 @@ -console.log('hello'); diff --git a/test/diffs/insert.B.js b/test/diffs/insert.B.js deleted file mode 100644 index cc26b9ec3..000000000 --- a/test/diffs/insert.B.js +++ /dev/null @@ -1,2 +0,0 @@ -console.log('hello'); -console.log('world'); diff --git a/test/diffs/insert.split.js b/test/diffs/insert.split.js deleted file mode 100644 index 20d0d1bb5..000000000 --- a/test/diffs/insert.split.js +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - -
          1
              • console
              • .
              • log
              • (
              • 'hello'
              • )
            • ;
          • -
          1
              • console
              • .
              • log
              • (
              • 'hello'
              • )
            • ;
          • -
          2
              • console
              • .
              • log
              • (
              • 'world'
              • )
            • ;
          • -
          2
            3
              \ No newline at end of file diff --git a/test/diffs/jquery.A.js b/test/diffs/jquery.A.js deleted file mode 100644 index 0c451e49a..000000000 --- a/test/diffs/jquery.A.js +++ /dev/null @@ -1,27 +0,0 @@ -define( function() { - - // We have to close these tags to support XHTML (#13200) - var wrapMap = { - - // Support: IE9 - option: [ 1, "" ], - - // XHTML parsers do not magically insert elements in the - // same way that tag soup parsers do. So we cannot shorten - // this by omitting or other required elements. - thead: [ 1, "", "
              " ], - col: [ 2, "", "
              " ], - tr: [ 2, "", "
              " ], - td: [ 3, "", "
              " ], - - _default: [ 0, "", "" ] - }; - - // Support: IE9 - wrapMap.optgroup = wrapMap.option; - - wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; - wrapMap.th = wrapMap.td; - - return wrapMap; -} ); diff --git a/test/diffs/jquery.B.js b/test/diffs/jquery.B.js deleted file mode 100644 index bdf906733..000000000 --- a/test/diffs/jquery.B.js +++ /dev/null @@ -1,27 +0,0 @@ -define( function() { - - // We have to close these tags to support XHTML (#13200) - var wrapMap = { - - // Support: IE <=9 only - option: [ 1, "" ], - - // XHTML parsers do not magically insert elements in the - // same way that tag soup parsers do. So we cannot shorten - // this by omitting or other required elements. - thead: [ 1, "", "
              " ], - col: [ 2, "", "
              " ], - tr: [ 2, "", "
              " ], - td: [ 3, "", "
              " ], - - _default: [ 0, "", "" ] - }; - - // Support: IE <=9 only - wrapMap.optgroup = wrapMap.option; - - wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; - wrapMap.th = wrapMap.td; - - return wrapMap; -} ); diff --git a/test/diffs/jquery.patch.js b/test/diffs/jquery.patch.js deleted file mode 100644 index c71be0b2c..000000000 --- a/test/diffs/jquery.patch.js +++ /dev/null @@ -1,22 +0,0 @@ -diff --git a/test/diffs/jquery.A.js b/test/diffs/jquery.B.js -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/test/diffs/jquery.A.js -+++ b/test/diffs/jquery.B.js -@@ -3,7 +3,7 @@ - // We have to close these tags to support XHTML (#13200) - var wrapMap = { - -- // Support: IE9 -+ // Support: IE <=9 only - option: [ 1, "" ], - - // XHTML parsers do not magically insert elements in the -@@ -17,7 +17,7 @@ - _default: [ 0, "", "" ] - }; - -- // Support: IE9 -+ // Support: IE <=9 only - wrapMap.optgroup = wrapMap.option; - - wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; diff --git a/test/diffs/multiline-insert.A.js b/test/diffs/multiline-insert.A.js deleted file mode 100644 index cc26b9ec3..000000000 --- a/test/diffs/multiline-insert.A.js +++ /dev/null @@ -1,2 +0,0 @@ -console.log('hello'); -console.log('world'); diff --git a/test/diffs/multiline-insert.B.js b/test/diffs/multiline-insert.B.js deleted file mode 100644 index 477baf7ff..000000000 --- a/test/diffs/multiline-insert.B.js +++ /dev/null @@ -1,5 +0,0 @@ -console.log('hello'); -if (true) { - console.log('cruel'); -} -console.log('world'); diff --git a/test/diffs/multiline-insert.split.js b/test/diffs/multiline-insert.split.js deleted file mode 100644 index 70cdf91f9..000000000 --- a/test/diffs/multiline-insert.split.js +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - -
              1
                  • console
                  • .
                  • log
                  • (
                  • 'hello'
                  • )
                • ;
              • -
              1
                  • console
                  • .
                  • log
                  • (
                  • 'hello'
                  • )
                • ;
              • -
              2
                • if (
                • true
                • )
                  • { -
              3
                      • console
                      • .
                      • log
                      • (
                      • 'cruel'
                      • )
                    • ;
                  • -
              4
                  • }
              • -
              2
                  • console
                  • .
                  • log
                  • (
                  • 'world'
                  • )
                • ;
              • -
              5
                  • console
                  • .
                  • log
                  • (
                  • 'world'
                  • )
                • ;
              • -
              3
                6
                  \ No newline at end of file diff --git a/test/diffs/multiple-hunks.A.js b/test/diffs/multiple-hunks.A.js deleted file mode 100644 index 27c9a9eb1..000000000 --- a/test/diffs/multiple-hunks.A.js +++ /dev/null @@ -1,13 +0,0 @@ -define( function() { - console.log("foo"); - // A comment - // Another comment - // Another comment - // A comment - // Another comment - // Another comment - // A comment - // Another comment - // Another comment - console.log("bar"); -}); diff --git a/test/diffs/multiple-hunks.B.js b/test/diffs/multiple-hunks.B.js deleted file mode 100644 index 523aa0703..000000000 --- a/test/diffs/multiple-hunks.B.js +++ /dev/null @@ -1,13 +0,0 @@ -define( function() { - console.log("bar"); - // A comment - // Another comment - // Another comment - // A comment - // Another comment - // Another comment - // A comment - // Another comment - // Another comment - console.log("foo"); -}); diff --git a/test/diffs/multiple-hunks.patch.js b/test/diffs/multiple-hunks.patch.js deleted file mode 100644 index e923eb62e..000000000 --- a/test/diffs/multiple-hunks.patch.js +++ /dev/null @@ -1,18 +0,0 @@ -diff --git a/test/diffs/multiple-hunks.A.js b/test/diffs/multiple-hunks.B.js -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/test/diffs/multiple-hunks.A.js -+++ b/test/diffs/multiple-hunks.B.js -@@ -1,5 +1,5 @@ - define( function() { -- console.log("foo"); -+ console.log("bar"); - // A comment - // Another comment - // Another comment -@@ -9,6 +9,6 @@ - // A comment - // Another comment - // Another comment -- console.log("bar"); -+ console.log("foo"); - }); diff --git a/test/diffs/nested-insert.A.js b/test/diffs/nested-insert.A.js deleted file mode 100644 index ac1cf78b2..000000000 --- a/test/diffs/nested-insert.A.js +++ /dev/null @@ -1,3 +0,0 @@ -if (true) { - console.log('hello'); -} diff --git a/test/diffs/nested-insert.B.js b/test/diffs/nested-insert.B.js deleted file mode 100644 index bd45024a7..000000000 --- a/test/diffs/nested-insert.B.js +++ /dev/null @@ -1,4 +0,0 @@ -if (true) { - console.log('hello'); - console.log('world'); -} diff --git a/test/diffs/nested-insert.split.js b/test/diffs/nested-insert.split.js deleted file mode 100644 index c15c67c90..000000000 --- a/test/diffs/nested-insert.split.js +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - -
                  1
                    • if (
                    • true
                    • )
                      • { -
                  1
                    • if (
                    • true
                    • )
                      • { -
                  2
                          • console
                          • .
                          • log
                          • (
                          • 'hello'
                          • )
                        • ;
                      • -
                  2
                          • console
                          • .
                          • log
                          • (
                          • 'hello'
                          • )
                        • ;
                      • -
                  3
                          • console
                          • .
                          • log
                          • (
                          • 'world'
                          • )
                        • ;
                      • -
                  3
                      • }
                  • -
                  4
                      • }
                  • -
                  4
                    5
                      \ No newline at end of file diff --git a/test/diffs/newline-at-eof.A.js b/test/diffs/newline-at-eof.A.js deleted file mode 100644 index 65e362e70..000000000 --- a/test/diffs/newline-at-eof.A.js +++ /dev/null @@ -1 +0,0 @@ -console.log("hello, world"); diff --git a/test/diffs/newline-at-eof.B.js b/test/diffs/newline-at-eof.B.js deleted file mode 100644 index e672b95ff..000000000 --- a/test/diffs/newline-at-eof.B.js +++ /dev/null @@ -1,3 +0,0 @@ -console.log("hello, world"); - -console.log("insertion"); diff --git a/test/diffs/newline-at-eof.json.js b/test/diffs/newline-at-eof.json.js deleted file mode 100644 index aa7265b10..000000000 --- a/test/diffs/newline-at-eof.json.js +++ /dev/null @@ -1 +0,0 @@ -{"oids":["0000000000000000000000000000000000000000","0000000000000000000000000000000000000000"],"paths":["test/diffs/newline-at-eof.A.js","test/diffs/newline-at-eof.B.js"],"rows":[[{"terms":[{"category":"Program","children":[{"category":"ExpressionStatements","children":[{"category":"FunctionCall","children":[{"category":"Identifier","range":[0,7]},{"category":"Identifier","range":[8,11]},{"category":"StringLiteral","range":[12,26]}],"range":[0,27]}],"range":[0,28]}],"range":[0,29]}],"hasChanges":false,"range":[0,29],"number":1},{"terms":[{"category":"Program","children":[{"category":"ExpressionStatements","children":[{"category":"FunctionCall","children":[{"category":"Identifier","range":[0,7]},{"category":"Identifier","range":[8,11]},{"category":"StringLiteral","range":[12,26]}],"range":[0,27]}],"range":[0,28]}],"range":[0,29]}],"hasChanges":false,"range":[0,29],"number":1}],[{"terms":[{"category":"Program","children":[],"range":[29,29]}],"hasChanges":false,"range":[29,29],"number":2},{"terms":[{"category":"Program","children":[],"range":[29,30]}],"hasChanges":false,"range":[29,30],"number":2}],[{"terms":[{"category":"Program","children":[{"category":"ExpressionStatements","children":[{"category":"FunctionCall","children":[{"category":"Identifier","range":[30,37]},{"category":"Identifier","range":[38,41]},{"category":"StringLiteral","range":[42,53]}],"range":[30,54]}],"patch":"insert","range":[30,55]}],"range":[30,56]}],"hasChanges":true,"range":[30,56],"number":3}],[{"terms":[{"category":"Program","children":[],"range":[56,56]}],"hasChanges":false,"range":[56,56],"number":4}]]} \ No newline at end of file diff --git a/test/diffs/newline-at-eof.patch.js b/test/diffs/newline-at-eof.patch.js deleted file mode 100644 index ff7530a52..000000000 --- a/test/diffs/newline-at-eof.patch.js +++ /dev/null @@ -1,8 +0,0 @@ -diff --git a/test/diffs/newline-at-eof.A.js b/test/diffs/newline-at-eof.B.js -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/test/diffs/newline-at-eof.A.js -+++ b/test/diffs/newline-at-eof.B.js -@@ -1,2 +1,4 @@ - console.log("hello, world"); - -+console.log("insertion"); diff --git a/test/diffs/newline-at-eof.split.js b/test/diffs/newline-at-eof.split.js deleted file mode 100644 index 499ac877c..000000000 --- a/test/diffs/newline-at-eof.split.js +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - -
                      1
                          • console
                          • .
                          • log
                          • (
                          • "hello, world"
                          • )
                        • ;
                      • -
                      1
                          • console
                          • .
                          • log
                          • (
                          • "hello, world"
                          • )
                        • ;
                      • -
                      2
                        2
                          -
                        3
                            • console
                            • .
                            • log
                            • (
                            • "insertion"
                            • )
                          • ;
                        • -
                        4
                          \ No newline at end of file diff --git a/test/diffs/no-newline-at-eof.A.js b/test/diffs/no-newline-at-eof.A.js deleted file mode 100644 index 4336a74b3..000000000 --- a/test/diffs/no-newline-at-eof.A.js +++ /dev/null @@ -1 +0,0 @@ -console.log("hello, world"); \ No newline at end of file diff --git a/test/diffs/no-newline-at-eof.B.js b/test/diffs/no-newline-at-eof.B.js deleted file mode 100644 index 3dc95cb30..000000000 --- a/test/diffs/no-newline-at-eof.B.js +++ /dev/null @@ -1,3 +0,0 @@ -console.log("hello, world"); - -console.log("insertion"); \ No newline at end of file diff --git a/test/diffs/no-newline-at-eof.json.js b/test/diffs/no-newline-at-eof.json.js deleted file mode 100644 index f2344694e..000000000 --- a/test/diffs/no-newline-at-eof.json.js +++ /dev/null @@ -1 +0,0 @@ -{"oids":["0000000000000000000000000000000000000000","0000000000000000000000000000000000000000"],"paths":["test/diffs/no-newline-at-eof.A.js","test/diffs/no-newline-at-eof.B.js"],"rows":[[{"terms":[{"category":"Program","children":[{"category":"ExpressionStatements","children":[{"category":"FunctionCall","children":[{"category":"Identifier","range":[0,7]},{"category":"Identifier","range":[8,11]},{"category":"StringLiteral","range":[12,26]}],"range":[0,27]}],"range":[0,28]}],"range":[0,28]}],"hasChanges":false,"range":[0,28],"number":1},{"terms":[{"category":"Program","children":[{"category":"ExpressionStatements","children":[{"category":"FunctionCall","children":[{"category":"Identifier","range":[0,7]},{"category":"Identifier","range":[8,11]},{"category":"StringLiteral","range":[12,26]}],"range":[0,27]}],"range":[0,28]}],"range":[0,29]}],"hasChanges":false,"range":[0,29],"number":1}],[{"terms":[{"category":"Program","children":[],"range":[29,30]}],"hasChanges":false,"range":[29,30],"number":2}],[{"terms":[{"category":"Program","children":[{"category":"ExpressionStatements","children":[{"category":"FunctionCall","children":[{"category":"Identifier","range":[30,37]},{"category":"Identifier","range":[38,41]},{"category":"StringLiteral","range":[42,53]}],"range":[30,54]}],"patch":"insert","range":[30,55]}],"range":[30,55]}],"hasChanges":true,"range":[30,55],"number":3}]]} \ No newline at end of file diff --git a/test/diffs/no-newline-at-eof.patch.js b/test/diffs/no-newline-at-eof.patch.js deleted file mode 100644 index 19dabe4b3..000000000 --- a/test/diffs/no-newline-at-eof.patch.js +++ /dev/null @@ -1,9 +0,0 @@ -diff --git a/test/diffs/no-newline-at-eof.A.js b/test/diffs/no-newline-at-eof.B.js -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/test/diffs/no-newline-at-eof.A.js -+++ b/test/diffs/no-newline-at-eof.B.js -@@ -1,1 +1,3 @@ - console.log("hello, world"); - -+console.log("insertion"); -\ No newline at end of file diff --git a/test/diffs/no-newline-at-eof.split.js b/test/diffs/no-newline-at-eof.split.js deleted file mode 100644 index e673f63c1..000000000 --- a/test/diffs/no-newline-at-eof.split.js +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - -
                          1
                              • console
                              • .
                              • log
                              • (
                              • "hello, world"
                              • )
                            • ;
                          1
                              • console
                              • .
                              • log
                              • (
                              • "hello, world"
                              • )
                            • ;
                          • -
                          2
                            -
                          3
                              • console
                              • .
                              • log
                              • (
                              • "insertion"
                              • )
                            • ;
                          \ No newline at end of file diff --git a/test/diffs/reformat.A.js b/test/diffs/reformat.A.js deleted file mode 100644 index 4a30a36c8..000000000 --- a/test/diffs/reformat.A.js +++ /dev/null @@ -1 +0,0 @@ -[ bar ]; \ No newline at end of file diff --git a/test/diffs/reformat.B.js b/test/diffs/reformat.B.js deleted file mode 100644 index e128a5f99..000000000 --- a/test/diffs/reformat.B.js +++ /dev/null @@ -1,3 +0,0 @@ -[ - bar -]; \ No newline at end of file diff --git a/test/diffs/reformat.split.js b/test/diffs/reformat.split.js deleted file mode 100644 index 2b799ebb2..000000000 --- a/test/diffs/reformat.split.js +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - -
                          1
                              • [ -
                          1
                              • [
                              • bar
                              • ]
                            • ;
                          2
                              • bar
                              • -
                          3
                              • ]
                            • ;
                          \ No newline at end of file diff --git a/test/fixtures/profile/javascript/jquery-large-after.js b/test/fixtures/profile/javascript/jquery-large-after.js new file mode 100644 index 000000000..590aaadac --- /dev/null +++ b/test/fixtures/profile/javascript/jquery-large-after.js @@ -0,0 +1,875 @@ +var jQuery = (function() { + +// Define a local copy of jQuery +var jQuery = function( selector, context ) { + // The jQuery object is actually just the init constructor 'enhanced' + return new jQuery.fn.init( selector, context ); + }, + + // Map over jQuery in case of overwrite + _jQuery = window.jQuery, + + // Map over the $ in case of overwrite + _$ = window.$, + + // A central reference to the root jQuery(document) + rootjQuery, + + // A simple way to check for HTML strings or ID strings + // (both of which we optimize for) + quickExpr = /^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/, + + // Is it a simple selector + isSimple = /^.[^:#\[\.,]*$/, + + // Check if a string has a non-whitespace character in it + rnotwhite = /\S/, + rwhite = /\s/, + + // Used for trimming whitespace + trimLeft = /^\s+/, + trimRight = /\s+$/, + + // Check for non-word characters + rnonword = /\W/, + + // Match a standalone tag + rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/, + + // JSON RegExp + rvalidchars = /^[\],:{}\s]*$/, + rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, + rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, + rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, + + // Useragent RegExp + rwebkit = /(webkit)[ \/]([\w.]+)/, + ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/, + rmsie = /(msie) ([\w.]+)/, + rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/, + + // Keep a UserAgent string for use with jQuery.browser + userAgent = navigator.userAgent, + + // For matching the engine and version of the browser + browserMatch, + + // Has the ready events already been bound? + readyBound = false, + + // The functions to execute on DOM ready + readyList = [], + + // The ready event handler + DOMContentLoaded, + + // Save a reference to some core methods + toString = Object.prototype.toString, + hasOwn = Object.prototype.hasOwnProperty, + push = Array.prototype.push, + slice = Array.prototype.slice, + trim = String.prototype.trim, + indexOf = Array.prototype.indexOf, + + // [[Class]] -> type pairs + class2type = {}; + +jQuery.fn = jQuery.prototype = { + init: function( selector, context ) { + var match, elem, ret, doc; + + // Handle $(""), $(null), or $(undefined) + if ( !selector ) { + return this; + } + + // Handle $(DOMElement) + if ( selector.nodeType ) { + this.context = this[0] = selector; + this.length = 1; + return this; + } + + // The body element only exists once, optimize finding it + if ( selector === "body" && !context ) { + this.context = document; + this[0] = document.body; + this.selector = "body"; + this.length = 1; + return this; + } + + // Handle HTML strings + if ( typeof selector === "string" ) { + // Are we dealing with HTML string or an ID? + match = quickExpr.exec( selector ); + + // Verify a match, and that no context was specified for #id + if ( match && (match[1] || !context) ) { + + // HANDLE: $(html) -> $(array) + if ( match[1] ) { + doc = (context ? context.ownerDocument || context : document); + + // If a single string is passed in and it's a single tag + // just do a createElement and skip the rest + ret = rsingleTag.exec( selector ); + + if ( ret ) { + if ( jQuery.isPlainObject( context ) ) { + selector = [ document.createElement( ret[1] ) ]; + jQuery.fn.attr.call( selector, context, true ); + + } else { + selector = [ doc.createElement( ret[1] ) ]; + } + + } else { + ret = jQuery.buildFragment( [ match[1] ], [ doc ] ); + selector = (ret.cacheable ? ret.fragment.cloneNode(true) : ret.fragment).childNodes; + } + + return jQuery.merge( this, selector ); + + // HANDLE: $("#id") + } else { + elem = document.getElementById( match[2] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id !== match[2] ) { + return rootjQuery.find( selector ); + } + + // Otherwise, we inject the element directly into the jQuery object + this.length = 1; + this[0] = elem; + } + + this.context = document; + this.selector = selector; + return this; + } + + // HANDLE: $("TAG") + } else if ( !context && !rnonword.test( selector ) ) { + this.selector = selector; + this.context = document; + selector = document.getElementsByTagName( selector ); + return jQuery.merge( this, selector ); + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return (context || rootjQuery).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return jQuery( context ).find( selector ); + } + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + return rootjQuery.ready( selector ); + } + + if (selector.selector !== undefined) { + this.selector = selector.selector; + this.context = selector.context; + } + + return jQuery.makeArray( selector, this ); + }, + + // Start with an empty selector + selector: "", + + // The current version of jQuery being used + jquery: "@VERSION", + + // The default length of a jQuery object is 0 + length: 0, + + // The number of elements contained in the matched element set + size: function() { + return this.length; + }, + + toArray: function() { + return slice.call( this, 0 ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + return num == null ? + + // Return a 'clean' array + this.toArray() : + + // Return just the object + ( num < 0 ? this.slice(num)[ 0 ] : this[ num ] ); + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems, name, selector ) { + // Build a new jQuery matched element set + var ret = jQuery(); + + if ( jQuery.isArray( elems ) ) { + push.apply( ret, elems ); + + } else { + jQuery.merge( ret, elems ); + } + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + ret.context = this.context; + + if ( name === "find" ) { + ret.selector = this.selector + (this.selector ? " " : "") + selector; + } else if ( name ) { + ret.selector = this.selector + "." + name + "(" + selector + ")"; + } + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + // (You can seed the arguments with an array of args, but this is + // only used internally.) + each: function( callback, args ) { + return jQuery.each( this, callback, args ); + }, + + ready: function( fn ) { + // Attach the listeners + jQuery.bindReady(); + + // If the DOM is already ready + if ( jQuery.isReady ) { + // Execute the function immediately + fn.call( document, jQuery ); + + // Otherwise, remember the function for later + } else if ( readyList ) { + // Add the function to the wait list + readyList.push( fn ); + } + + return this; + }, + + eq: function( i ) { + return i === -1 ? + this.slice( i ) : + this.slice( i, +i + 1 ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ), + "slice", slice.call(arguments).join(",") ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map(this, function( elem, i ) { + return callback.call( elem, i, elem ); + })); + }, + + end: function() { + return this.prevObject || jQuery(null); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: [].sort, + splice: [].splice +}; + +// Give the init function the jQuery prototype for later instantiation +jQuery.fn.init.prototype = jQuery.fn; + +jQuery.extend = jQuery.fn.extend = function() { + // copy reference to target object + var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options, name, src, copy, copyIsArray; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction(target) ) { + target = {}; + } + + // extend jQuery itself if only one argument is passed + if ( length === i ) { + target = this; + --i; + } + + for ( ; i < length; i++ ) { + // Only deal with non-null/undefined values + if ( (options = arguments[ i ]) != null ) { + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { + if ( copyIsArray ) { + copyIsArray = false; + clone = src && jQuery.isArray(src) ? src : []; + } else { + clone = src && jQuery.isPlainObject(src) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend({ + noConflict: function( deep ) { + window.$ = _$; + + if ( deep ) { + window.jQuery = _jQuery; + } + + return jQuery; + }, + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Handle when the DOM is ready + ready: function( wait ) { + // A third-party is pushing the ready event forwards + if ( wait === true ) { + jQuery.readyWait--; + } + + // Make sure that the DOM is not already loaded + if ( !jQuery.readyWait || (wait !== true && !jQuery.isReady) ) { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( !document.body ) { + return setTimeout( jQuery.ready, 13 ); + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + if ( readyList ) { + // Execute all of them + var fn, i = 0; + while ( (fn = readyList[ i++ ]) ) { + fn.call( document, jQuery ); + } + + // Reset the list of functions + readyList = null; + } + + // Trigger any bound ready events + if ( jQuery.fn.triggerHandler ) { + jQuery( document ).triggerHandler( "ready" ); + } + } + }, + + bindReady: function() { + if ( readyBound ) { + return; + } + + readyBound = true; + + // Catch cases where $(document).ready() is called after the + // browser event has already occurred. + if ( document.readyState === "complete" ) { + return jQuery.ready(); + } + + // Mozilla, Opera and webkit nightlies currently support this event + if ( document.addEventListener ) { + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", jQuery.ready, false ); + + // If IE event model is used + } else if ( document.attachEvent ) { + // ensure firing before onload, + // maybe late but safe also for iframes + document.attachEvent("onreadystatechange", DOMContentLoaded); + + // A fallback to window.onload, that will always work + window.attachEvent( "onload", jQuery.ready ); + + // If IE and not a frame + // continually check to see if the document is ready + var toplevel = false; + + try { + toplevel = window.frameElement == null; + } catch(e) {} + + if ( document.documentElement.doScroll && toplevel ) { + doScrollCheck(); + } + } + }, + + // See test/unit/core.js for details concerning isFunction. + // Since version 1.3, DOM methods and functions like alert + // aren't supported. They return false on IE (#2968). + isFunction: function( obj ) { + return jQuery.type(obj) === "function"; + }, + + isArray: Array.isArray || function( obj ) { + return jQuery.type(obj) === "array"; + }, + + // A crude way of determining if an object is a window + isWindow: function( obj ) { + return obj && typeof obj === "object" && "setInterval" in obj; + }, + + type: function( obj ) { + return obj == null ? + String( obj ) : + class2type[ toString.call(obj) ] || "object"; + }, + + isPlainObject: function( obj ) { + // Must be an Object. + // Because of IE, we also have to check the presence of the constructor property. + // Make sure that DOM nodes and window objects don't pass through, as well + if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { + return false; + } + + // Not own constructor property must be Object + if ( obj.constructor && + !hasOwn.call(obj, "constructor") && + !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { + return false; + } + + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + + var key; + for ( key in obj ) {} + + return key === undefined || hasOwn.call( obj, key ); + }, + + isEmptyObject: function( obj ) { + for ( var name in obj ) { + return false; + } + return true; + }, + + error: function( msg ) { + throw msg; + }, + + parseJSON: function( data ) { + if ( typeof data !== "string" || !data ) { + return null; + } + + // Make sure leading/trailing whitespace is removed (IE can't handle it) + data = jQuery.trim( data ); + + // Make sure the incoming data is actual JSON + // Logic borrowed from http://json.org/json2.js + if ( rvalidchars.test(data.replace(rvalidescape, "@") + .replace(rvalidtokens, "]") + .replace(rvalidbraces, "")) ) { + + // Try to use the native JSON parser first + return window.JSON && window.JSON.parse ? + window.JSON.parse( data ) : + (new Function("return " + data))(); + + } else { + jQuery.error( "Invalid JSON: " + data ); + } + }, + + noop: function() {}, + + // Evalulates a script in a global context + globalEval: function( data ) { + if ( data && rnotwhite.test(data) ) { + // Inspired by code by Andrea Giammarchi + // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html + var head = document.getElementsByTagName("head")[0] || document.documentElement, + script = document.createElement("script"); + + script.type = "text/javascript"; + + if ( jQuery.support.scriptEval ) { + script.appendChild( document.createTextNode( data ) ); + } else { + script.text = data; + } + + // Use insertBefore instead of appendChild to circumvent an IE6 bug. + // This arises when a base node is used (#2709). + head.insertBefore( script, head.firstChild ); + head.removeChild( script ); + } + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase(); + }, + + // args is for internal usage only + each: function( object, callback, args ) { + var name, i = 0, + length = object.length, + isObj = length === undefined || jQuery.isFunction(object); + + if ( args ) { + if ( isObj ) { + for ( name in object ) { + if ( callback.apply( object[ name ], args ) === false ) { + break; + } + } + } else { + for ( ; i < length; ) { + if ( callback.apply( object[ i++ ], args ) === false ) { + break; + } + } + } + + // A special, fast, case for the most common use of each + } else { + if ( isObj ) { + for ( name in object ) { + if ( callback.call( object[ name ], name, object[ name ] ) === false ) { + break; + } + } + } else { + for ( var value = object[0]; + i < length && callback.call( value, i, value ) !== false; value = object[++i] ) {} + } + } + + return object; + }, + + // Use native String.trim function wherever possible + trim: trim ? + function( text ) { + return text == null ? + "" : + trim.call( text ); + } : + + // Otherwise use our own trimming functionality + function( text ) { + return text == null ? + "" : + text.toString().replace( trimLeft, "" ).replace( trimRight, "" ); + }, + + // results is for internal usage only + makeArray: function( array, results ) { + var ret = results || []; + + if ( array != null ) { + // The window, strings (and functions) also have 'length' + // The extra typeof function check is to prevent crashes + // in Safari 2 (See: #3039) + // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930 + var type = jQuery.type(array); + + if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) { + push.call( ret, array ); + } else { + jQuery.merge( ret, array ); + } + } + + return ret; + }, + + inArray: function( elem, array ) { + if ( array.indexOf ) { + return array.indexOf( elem ); + } + + for ( var i = 0, length = array.length; i < length; i++ ) { + if ( array[ i ] === elem ) { + return i; + } + } + + return -1; + }, + + merge: function( first, second ) { + var i = first.length, j = 0; + + if ( typeof second.length === "number" ) { + for ( var l = second.length; j < l; j++ ) { + first[ i++ ] = second[ j ]; + } + + } else { + while ( second[j] !== undefined ) { + first[ i++ ] = second[ j++ ]; + } + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, inv ) { + var ret = [], retVal; + inv = !!inv; + + // Go through the array, only saving the items + // that pass the validator function + for ( var i = 0, length = elems.length; i < length; i++ ) { + retVal = !!callback( elems[ i ], i ); + if ( inv !== retVal ) { + ret.push( elems[ i ] ); + } + } + + return ret; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var ret = [], value; + + // Go through the array, translating each of the items to their + // new value (or values). + for ( var i = 0, length = elems.length; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + + return ret.concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + proxy: function( fn, proxy, thisObject ) { + if ( arguments.length === 2 ) { + if ( typeof proxy === "string" ) { + thisObject = fn; + fn = thisObject[ proxy ]; + proxy = undefined; + + } else if ( proxy && !jQuery.isFunction( proxy ) ) { + thisObject = proxy; + proxy = undefined; + } + } + + if ( !proxy && fn ) { + proxy = function() { + return fn.apply( thisObject || this, arguments ); + }; + } + + // Set the guid of unique handler to the same of original handler, so it can be removed + if ( fn ) { + proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++; + } + + // So proxy can be declared as an argument + return proxy; + }, + + // Mutifunctional method to get and set values to a collection + // The value/s can be optionally by executed if its a function + access: function( elems, key, value, exec, fn, pass ) { + var length = elems.length; + + // Setting many attributes + if ( typeof key === "object" ) { + for ( var k in key ) { + jQuery.access( elems, k, key[k], exec, fn, value ); + } + return elems; + } + + // Setting one attribute + if ( value !== undefined ) { + // Optionally, function values get executed if exec is true + exec = !pass && exec && jQuery.isFunction(value); + + for ( var i = 0; i < length; i++ ) { + fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); + } + + return elems; + } + + // Getting an attribute + return length ? fn( elems[0], key ) : undefined; + }, + + now: function() { + return (new Date()).getTime(); + }, + + // Use of jQuery.browser is frowned upon. + // More details: http://docs.jquery.com/Utilities/jQuery.browser + uaMatch: function( ua ) { + ua = ua.toLowerCase(); + + var match = rwebkit.exec( ua ) || + ropera.exec( ua ) || + rmsie.exec( ua ) || + ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) || + []; + + return { browser: match[1] || "", version: match[2] || "0" }; + }, + + browser: {} +}); + +// Populate the class2type map +jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +}); + +browserMatch = jQuery.uaMatch( userAgent ); +if ( browserMatch.browser ) { + jQuery.browser[ browserMatch.browser ] = true; + jQuery.browser.version = browserMatch.version; +} + +// Deprecated, use jQuery.browser.webkit instead +if ( jQuery.browser.webkit ) { + jQuery.browser.safari = true; +} + +if ( indexOf ) { + jQuery.inArray = function( elem, array ) { + return indexOf.call( array, elem ); + }; +} + +// Verify that \s matches non-breaking spaces +// (IE fails on this test) +if ( !rwhite.test( "\xA0" ) ) { + trimLeft = /^[\s\xA0]+/; + trimRight = /[\s\xA0]+$/; +} + +// All jQuery objects should point back to these +rootjQuery = jQuery(document); + +// Cleanup functions for the document ready method +if ( document.addEventListener ) { + DOMContentLoaded = function() { + document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + jQuery.ready(); + }; + +} else if ( document.attachEvent ) { + DOMContentLoaded = function() { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( document.readyState === "complete" ) { + document.detachEvent( "onreadystatechange", DOMContentLoaded ); + jQuery.ready(); + } + }; +} + +// The DOM ready check for Internet Explorer +function doScrollCheck() { + if ( jQuery.isReady ) { + return; + } + + try { + // If IE is used, use the trick by Diego Perini + // http://javascript.nwbox.com/IEContentLoaded/ + document.documentElement.doScroll("left"); + } catch(e) { + setTimeout( doScrollCheck, 1 ); + return; + } + + // and execute any waiting functions + jQuery.ready(); +} + +// Expose jQuery to the global object +return (window.jQuery = window.$ = jQuery); + +})(); diff --git a/test/fixtures/profile/javascript/jquery-large-before.js b/test/fixtures/profile/javascript/jquery-large-before.js new file mode 100644 index 000000000..730e2cdf8 --- /dev/null +++ b/test/fixtures/profile/javascript/jquery-large-before.js @@ -0,0 +1,863 @@ +var jQuery = (function() { + +// Define a local copy of jQuery +var jQuery = function( selector, context ) { + // The jQuery object is actually just the init constructor 'enhanced' + return new jQuery.fn.init( selector, context ); + }, + + // Map over jQuery in case of overwrite + _jQuery = window.jQuery, + + // Map over the $ in case of overwrite + _$ = window.$, + + // A central reference to the root jQuery(document) + rootjQuery, + + // A simple way to check for HTML strings or ID strings + // (both of which we optimize for) + quickExpr = /^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/, + + // Is it a simple selector + isSimple = /^.[^:#\[\.,]*$/, + + // Check if a string has a non-whitespace character in it + rnotwhite = /\S/, + rwhite = /\s/, + + // Used for trimming whitespace + trimLeft = /^\s+/, + trimRight = /\s+$/, + + // Check for non-word characters + rnonword = /\W/, + + // Match a standalone tag + rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/, + + // JSON RegExp + rvalidchars = /^[\],:{}\s]*$/, + rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, + rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, + rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, + + // Useragent RegExp + rwebkit = /(webkit)[ \/]([\w.]+)/, + ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/, + rmsie = /(msie) ([\w.]+)/, + rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/, + + // Keep a UserAgent string for use with jQuery.browser + userAgent = navigator.userAgent, + + // For matching the engine and version of the browser + browserMatch, + + // Has the ready events already been bound? + readyBound = false, + + // The functions to execute on DOM ready + readyList = [], + + // The ready event handler + DOMContentLoaded, + + // Save a reference to some core methods + toString = Object.prototype.toString, + hasOwn = Object.prototype.hasOwnProperty, + push = Array.prototype.push, + slice = Array.prototype.slice, + trim = String.prototype.trim, + indexOf = Array.prototype.indexOf; + +jQuery.fn = jQuery.prototype = { + init: function( selector, context ) { + var match, elem, ret, doc; + + // Handle $(""), $(null), or $(undefined) + if ( !selector ) { + return this; + } + + // Handle $(DOMElement) + if ( selector.nodeType ) { + this.context = this[0] = selector; + this.length = 1; + return this; + } + + // The body element only exists once, optimize finding it + if ( selector === "body" && !context ) { + this.context = document; + this[0] = document.body; + this.selector = "body"; + this.length = 1; + return this; + } + + // Handle HTML strings + if ( typeof selector === "string" ) { + // Are we dealing with HTML string or an ID? + match = quickExpr.exec( selector ); + + // Verify a match, and that no context was specified for #id + if ( match && (match[1] || !context) ) { + + // HANDLE: $(html) -> $(array) + if ( match[1] ) { + doc = (context ? context.ownerDocument || context : document); + + // If a single string is passed in and it's a single tag + // just do a createElement and skip the rest + ret = rsingleTag.exec( selector ); + + if ( ret ) { + if ( jQuery.isPlainObject( context ) ) { + selector = [ document.createElement( ret[1] ) ]; + jQuery.fn.attr.call( selector, context, true ); + + } else { + selector = [ doc.createElement( ret[1] ) ]; + } + + } else { + ret = jQuery.buildFragment( [ match[1] ], [ doc ] ); + selector = (ret.cacheable ? ret.fragment.cloneNode(true) : ret.fragment).childNodes; + } + + return jQuery.merge( this, selector ); + + // HANDLE: $("#id") + } else { + elem = document.getElementById( match[2] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id !== match[2] ) { + return rootjQuery.find( selector ); + } + + // Otherwise, we inject the element directly into the jQuery object + this.length = 1; + this[0] = elem; + } + + this.context = document; + this.selector = selector; + return this; + } + + // HANDLE: $("TAG") + } else if ( !context && !rnonword.test( selector ) ) { + this.selector = selector; + this.context = document; + selector = document.getElementsByTagName( selector ); + return jQuery.merge( this, selector ); + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return (context || rootjQuery).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return jQuery( context ).find( selector ); + } + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + return rootjQuery.ready( selector ); + } + + if (selector.selector !== undefined) { + this.selector = selector.selector; + this.context = selector.context; + } + + return jQuery.makeArray( selector, this ); + }, + + // Start with an empty selector + selector: "", + + // The current version of jQuery being used + jquery: "@VERSION", + + // The default length of a jQuery object is 0 + length: 0, + + // The number of elements contained in the matched element set + size: function() { + return this.length; + }, + + toArray: function() { + return slice.call( this, 0 ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + return num == null ? + + // Return a 'clean' array + this.toArray() : + + // Return just the object + ( num < 0 ? this.slice(num)[ 0 ] : this[ num ] ); + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems, name, selector ) { + // Build a new jQuery matched element set + var ret = jQuery(); + + if ( jQuery.isArray( elems ) ) { + push.apply( ret, elems ); + + } else { + jQuery.merge( ret, elems ); + } + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + ret.context = this.context; + + if ( name === "find" ) { + ret.selector = this.selector + (this.selector ? " " : "") + selector; + } else if ( name ) { + ret.selector = this.selector + "." + name + "(" + selector + ")"; + } + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + // (You can seed the arguments with an array of args, but this is + // only used internally.) + each: function( callback, args ) { + return jQuery.each( this, callback, args ); + }, + + ready: function( fn ) { + // Attach the listeners + jQuery.bindReady(); + + // If the DOM is already ready + if ( jQuery.isReady ) { + // Execute the function immediately + fn.call( document, jQuery ); + + // Otherwise, remember the function for later + } else if ( readyList ) { + // Add the function to the wait list + readyList.push( fn ); + } + + return this; + }, + + eq: function( i ) { + return i === -1 ? + this.slice( i ) : + this.slice( i, +i + 1 ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ), + "slice", slice.call(arguments).join(",") ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map(this, function( elem, i ) { + return callback.call( elem, i, elem ); + })); + }, + + end: function() { + return this.prevObject || jQuery(null); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: [].sort, + splice: [].splice +}; + +// Give the init function the jQuery prototype for later instantiation +jQuery.fn.init.prototype = jQuery.fn; + +jQuery.extend = jQuery.fn.extend = function() { + // copy reference to target object + var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options, name, src, copy; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction(target) ) { + target = {}; + } + + // extend jQuery itself if only one argument is passed + if ( length === i ) { + target = this; + --i; + } + + for ( ; i < length; i++ ) { + // Only deal with non-null/undefined values + if ( (options = arguments[ i ]) != null ) { + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging object literal values or arrays + if ( deep && copy && ( jQuery.isPlainObject(copy) || jQuery.isArray(copy) ) ) { + var clone = src && ( jQuery.isPlainObject(src) || jQuery.isArray(src) ) ? src + : jQuery.isArray(copy) ? [] : {}; + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend({ + noConflict: function( deep ) { + window.$ = _$; + + if ( deep ) { + window.jQuery = _jQuery; + } + + return jQuery; + }, + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Handle when the DOM is ready + ready: function( wait ) { + // A third-party is pushing the ready event forwards + if ( wait === true ) { + jQuery.readyWait--; + } + + // Make sure that the DOM is not already loaded + if ( !jQuery.readyWait || (wait !== true && !jQuery.isReady) ) { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( !document.body ) { + return setTimeout( jQuery.ready, 13 ); + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + if ( readyList ) { + // Execute all of them + var fn, i = 0; + while ( (fn = readyList[ i++ ]) ) { + fn.call( document, jQuery ); + } + + // Reset the list of functions + readyList = null; + } + + // Trigger any bound ready events + if ( jQuery.fn.triggerHandler ) { + jQuery( document ).triggerHandler( "ready" ); + } + } + }, + + bindReady: function() { + if ( readyBound ) { + return; + } + + readyBound = true; + + // Catch cases where $(document).ready() is called after the + // browser event has already occurred. + if ( document.readyState === "complete" ) { + return jQuery.ready(); + } + + // Mozilla, Opera and webkit nightlies currently support this event + if ( document.addEventListener ) { + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", jQuery.ready, false ); + + // If IE event model is used + } else if ( document.attachEvent ) { + // ensure firing before onload, + // maybe late but safe also for iframes + document.attachEvent("onreadystatechange", DOMContentLoaded); + + // A fallback to window.onload, that will always work + window.attachEvent( "onload", jQuery.ready ); + + // If IE and not a frame + // continually check to see if the document is ready + var toplevel = false; + + try { + toplevel = window.frameElement == null; + } catch(e) {} + + if ( document.documentElement.doScroll && toplevel ) { + doScrollCheck(); + } + } + }, + + // See test/unit/core.js for details concerning isFunction. + // Since version 1.3, DOM methods and functions like alert + // aren't supported. They return false on IE (#2968). + isFunction: function( obj ) { + return jQuery.type(obj) === "function"; + }, + + isArray: Array.isArray || function( obj ) { + return jQuery.type(obj) === "array"; + }, + + // A crude way of determining if an object is a window + isWindow: function( obj ) { + return obj && typeof obj === "object" && "setInterval" in obj; + }, + + type: function( obj ) { + return obj == null ? + String( obj ) : + toString.call(obj).slice(8, -1).toLowerCase(); + }, + + isPlainObject: function( obj ) { + // Must be an Object. + // Because of IE, we also have to check the presence of the constructor property. + // Make sure that DOM nodes and window objects don't pass through, as well + if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { + return false; + } + + // Not own constructor property must be Object + if ( obj.constructor && + !hasOwn.call(obj, "constructor") && + !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { + return false; + } + + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + + var key; + for ( key in obj ) {} + + return key === undefined || hasOwn.call( obj, key ); + }, + + isEmptyObject: function( obj ) { + for ( var name in obj ) { + return false; + } + return true; + }, + + error: function( msg ) { + throw msg; + }, + + parseJSON: function( data ) { + if ( typeof data !== "string" || !data ) { + return null; + } + + // Make sure leading/trailing whitespace is removed (IE can't handle it) + data = jQuery.trim( data ); + + // Make sure the incoming data is actual JSON + // Logic borrowed from http://json.org/json2.js + if ( rvalidchars.test(data.replace(rvalidescape, "@") + .replace(rvalidtokens, "]") + .replace(rvalidbraces, "")) ) { + + // Try to use the native JSON parser first + return window.JSON && window.JSON.parse ? + window.JSON.parse( data ) : + (new Function("return " + data))(); + + } else { + jQuery.error( "Invalid JSON: " + data ); + } + }, + + noop: function() {}, + + // Evalulates a script in a global context + globalEval: function( data ) { + if ( data && rnotwhite.test(data) ) { + // Inspired by code by Andrea Giammarchi + // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html + var head = document.getElementsByTagName("head")[0] || document.documentElement, + script = document.createElement("script"); + + script.type = "text/javascript"; + + if ( jQuery.support.scriptEval ) { + script.appendChild( document.createTextNode( data ) ); + } else { + script.text = data; + } + + // Use insertBefore instead of appendChild to circumvent an IE6 bug. + // This arises when a base node is used (#2709). + head.insertBefore( script, head.firstChild ); + head.removeChild( script ); + } + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase(); + }, + + // args is for internal usage only + each: function( object, callback, args ) { + var name, i = 0, + length = object.length, + isObj = length === undefined || jQuery.isFunction(object); + + if ( args ) { + if ( isObj ) { + for ( name in object ) { + if ( callback.apply( object[ name ], args ) === false ) { + break; + } + } + } else { + for ( ; i < length; ) { + if ( callback.apply( object[ i++ ], args ) === false ) { + break; + } + } + } + + // A special, fast, case for the most common use of each + } else { + if ( isObj ) { + for ( name in object ) { + if ( callback.call( object[ name ], name, object[ name ] ) === false ) { + break; + } + } + } else { + for ( var value = object[0]; + i < length && callback.call( value, i, value ) !== false; value = object[++i] ) {} + } + } + + return object; + }, + + // Use native String.trim function wherever possible + trim: trim ? + function( text ) { + return text == null ? + "" : + trim.call( text ); + } : + + // Otherwise use our own trimming functionality + function( text ) { + return text == null ? + "" : + text.toString().replace( trimLeft, "" ).replace( trimRight, "" ); + }, + + // results is for internal usage only + makeArray: function( array, results ) { + var ret = results || []; + + if ( array != null ) { + // The window, strings (and functions) also have 'length' + // The extra typeof function check is to prevent crashes + // in Safari 2 (See: #3039) + // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930 + var type = jQuery.type(array); + + if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) { + push.call( ret, array ); + } else { + jQuery.merge( ret, array ); + } + } + + return ret; + }, + + inArray: function( elem, array ) { + if ( array.indexOf ) { + return array.indexOf( elem ); + } + + for ( var i = 0, length = array.length; i < length; i++ ) { + if ( array[ i ] === elem ) { + return i; + } + } + + return -1; + }, + + merge: function( first, second ) { + var i = first.length, j = 0; + + if ( typeof second.length === "number" ) { + for ( var l = second.length; j < l; j++ ) { + first[ i++ ] = second[ j ]; + } + + } else { + while ( second[j] !== undefined ) { + first[ i++ ] = second[ j++ ]; + } + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, inv ) { + var ret = [], retVal; + inv = !!inv; + + // Go through the array, only saving the items + // that pass the validator function + for ( var i = 0, length = elems.length; i < length; i++ ) { + retVal = !!callback( elems[ i ], i ); + if ( inv !== retVal ) { + ret.push( elems[ i ] ); + } + } + + return ret; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var ret = [], value; + + // Go through the array, translating each of the items to their + // new value (or values). + for ( var i = 0, length = elems.length; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + + return ret.concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + proxy: function( fn, proxy, thisObject ) { + if ( arguments.length === 2 ) { + if ( typeof proxy === "string" ) { + thisObject = fn; + fn = thisObject[ proxy ]; + proxy = undefined; + + } else if ( proxy && !jQuery.isFunction( proxy ) ) { + thisObject = proxy; + proxy = undefined; + } + } + + if ( !proxy && fn ) { + proxy = function() { + return fn.apply( thisObject || this, arguments ); + }; + } + + // Set the guid of unique handler to the same of original handler, so it can be removed + if ( fn ) { + proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++; + } + + // So proxy can be declared as an argument + return proxy; + }, + + // Mutifunctional method to get and set values to a collection + // The value/s can be optionally by executed if its a function + access: function( elems, key, value, exec, fn, pass ) { + var length = elems.length; + + // Setting many attributes + if ( typeof key === "object" ) { + for ( var k in key ) { + jQuery.access( elems, k, key[k], exec, fn, value ); + } + return elems; + } + + // Setting one attribute + if ( value !== undefined ) { + // Optionally, function values get executed if exec is true + exec = !pass && exec && jQuery.isFunction(value); + + for ( var i = 0; i < length; i++ ) { + fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); + } + + return elems; + } + + // Getting an attribute + return length ? fn( elems[0], key ) : undefined; + }, + + now: function() { + return (new Date()).getTime(); + }, + + // Use of jQuery.browser is frowned upon. + // More details: http://docs.jquery.com/Utilities/jQuery.browser + uaMatch: function( ua ) { + ua = ua.toLowerCase(); + + var match = rwebkit.exec( ua ) || + ropera.exec( ua ) || + rmsie.exec( ua ) || + ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) || + []; + + return { browser: match[1] || "", version: match[2] || "0" }; + }, + + browser: {} +}); + +browserMatch = jQuery.uaMatch( userAgent ); +if ( browserMatch.browser ) { + jQuery.browser[ browserMatch.browser ] = true; + jQuery.browser.version = browserMatch.version; +} + +// Deprecated, use jQuery.browser.webkit instead +if ( jQuery.browser.webkit ) { + jQuery.browser.safari = true; +} + +if ( indexOf ) { + jQuery.inArray = function( elem, array ) { + return indexOf.call( array, elem ); + }; +} + +// Verify that \s matches non-breaking spaces +// (IE fails on this test) +if ( !rwhite.test( "\xA0" ) ) { + trimLeft = /^[\s\xA0]+/; + trimRight = /[\s\xA0]+$/; +} + +// All jQuery objects should point back to these +rootjQuery = jQuery(document); + +// Cleanup functions for the document ready method +if ( document.addEventListener ) { + DOMContentLoaded = function() { + document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + jQuery.ready(); + }; + +} else if ( document.attachEvent ) { + DOMContentLoaded = function() { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( document.readyState === "complete" ) { + document.detachEvent( "onreadystatechange", DOMContentLoaded ); + jQuery.ready(); + } + }; +} + +// The DOM ready check for Internet Explorer +function doScrollCheck() { + if ( jQuery.isReady ) { + return; + } + + try { + // If IE is used, use the trick by Diego Perini + // http://javascript.nwbox.com/IEContentLoaded/ + document.documentElement.doScroll("left"); + } catch(e) { + setTimeout( doScrollCheck, 1 ); + return; + } + + // and execute any waiting functions + jQuery.ready(); +} + +// Expose jQuery to the global object +return (window.jQuery = window.$ = jQuery); + +})(); diff --git a/test/fixtures/profile/javascript/jquery-medium-after.js b/test/fixtures/profile/javascript/jquery-medium-after.js new file mode 100644 index 000000000..7933873c4 --- /dev/null +++ b/test/fixtures/profile/javascript/jquery-medium-after.js @@ -0,0 +1,177 @@ +define( [ + "../core", + "../var/rnotwhite", + "../data/var/dataPriv", + "../core/init" +], function( jQuery, rnotwhite, dataPriv ) { + +var rclass = /[\t\r\n\f]/g; + +function getClass( elem ) { + return elem.getAttribute && elem.getAttribute( "class" ) || ""; +} + +jQuery.fn.extend( { + addClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( jQuery.isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).addClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + if ( typeof value === "string" && value ) { + classes = value.match( rnotwhite ) || []; + + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + cur = elem.nodeType === 1 && + ( " " + curValue + " " ).replace( rclass, " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + if ( cur.indexOf( " " + clazz + " " ) < 0 ) { + cur += clazz + " "; + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = jQuery.trim( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( jQuery.isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + if ( !arguments.length ) { + return this.attr( "class", "" ); + } + + if ( typeof value === "string" && value ) { + classes = value.match( rnotwhite ) || []; + + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + + // This expression is here for better compressibility (see addClass) + cur = elem.nodeType === 1 && + ( " " + curValue + " " ).replace( rclass, " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + + // Remove *all* instances + while ( cur.indexOf( " " + clazz + " " ) > -1 ) { + cur = cur.replace( " " + clazz + " ", " " ); + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = jQuery.trim( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value; + + if ( typeof stateVal === "boolean" && type === "string" ) { + return stateVal ? this.addClass( value ) : this.removeClass( value ); + } + + if ( jQuery.isFunction( value ) ) { + return this.each( function( i ) { + jQuery( this ).toggleClass( + value.call( this, i, getClass( this ), stateVal ), + stateVal + ); + } ); + } + + return this.each( function() { + var className, i, self, classNames; + + if ( type === "string" ) { + + // Toggle individual class names + i = 0; + self = jQuery( this ); + classNames = value.match( rnotwhite ) || []; + + while ( ( className = classNames[ i++ ] ) ) { + + // Check each className given, space separated list + if ( self.hasClass( className ) ) { + self.removeClass( className ); + } else { + self.addClass( className ); + } + } + + // Toggle whole class name + } else if ( value === undefined || type === "boolean" ) { + className = getClass( this ); + if ( className ) { + + // Store className if set + dataPriv.set( this, "__className__", className ); + } + + // If the element has a class name or if we're passed `false`, + // then remove the whole classname (if there was one, the above saved it). + // Otherwise bring back whatever was previously saved (if anything), + // falling back to the empty string if nothing was stored. + if ( this.setAttribute ) { + this.setAttribute( "class", + className || value === false ? + "" : + dataPriv.get( this, "__className__" ) || "" + ); + } + } + } ); + }, + + hasClass: function( selector ) { + var className, elem, + i = 0; + + className = " " + selector + " "; + while ( ( elem = this[ i++ ] ) ) { + if ( elem.nodeType === 1 && + ( " " + getClass( elem ) + " " ).replace( rclass, " " ) + .indexOf( className ) > -1 + ) { + return true; + } + } + + return false; + } +} ); + +} ); diff --git a/test/fixtures/profile/javascript/jquery-medium-before.js b/test/fixtures/profile/javascript/jquery-medium-before.js new file mode 100644 index 000000000..23b4cd6af --- /dev/null +++ b/test/fixtures/profile/javascript/jquery-medium-before.js @@ -0,0 +1,174 @@ +define( [ + "../core", + "../core/stripAndCollapse", + "../var/rnothtmlwhite", + "../data/var/dataPriv", + "../core/init" +], function( jQuery, stripAndCollapse, rnothtmlwhite, dataPriv ) { + +"use strict"; + +function getClass( elem ) { + return elem.getAttribute && elem.getAttribute( "class" ) || ""; +} + +jQuery.fn.extend( { + addClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( jQuery.isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).addClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + if ( typeof value === "string" && value ) { + classes = value.match( rnothtmlwhite ) || []; + + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + if ( cur.indexOf( " " + clazz + " " ) < 0 ) { + cur += clazz + " "; + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( jQuery.isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + if ( !arguments.length ) { + return this.attr( "class", "" ); + } + + if ( typeof value === "string" && value ) { + classes = value.match( rnothtmlwhite ) || []; + + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + + // This expression is here for better compressibility (see addClass) + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + + // Remove *all* instances + while ( cur.indexOf( " " + clazz + " " ) > -1 ) { + cur = cur.replace( " " + clazz + " ", " " ); + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value; + + if ( typeof stateVal === "boolean" && type === "string" ) { + return stateVal ? this.addClass( value ) : this.removeClass( value ); + } + + if ( jQuery.isFunction( value ) ) { + return this.each( function( i ) { + jQuery( this ).toggleClass( + value.call( this, i, getClass( this ), stateVal ), + stateVal + ); + } ); + } + + return this.each( function() { + var className, i, self, classNames; + + if ( type === "string" ) { + + // Toggle individual class names + i = 0; + self = jQuery( this ); + classNames = value.match( rnothtmlwhite ) || []; + + while ( ( className = classNames[ i++ ] ) ) { + + // Check each className given, space separated list + if ( self.hasClass( className ) ) { + self.removeClass( className ); + } else { + self.addClass( className ); + } + } + + // Toggle whole class name + } else if ( value === undefined || type === "boolean" ) { + className = getClass( this ); + if ( className ) { + + // Store className if set + dataPriv.set( this, "__className__", className ); + } + + // If the element has a class name or if we're passed `false`, + // then remove the whole classname (if there was one, the above saved it). + // Otherwise bring back whatever was previously saved (if anything), + // falling back to the empty string if nothing was stored. + if ( this.setAttribute ) { + this.setAttribute( "class", + className || value === false ? + "" : + dataPriv.get( this, "__className__" ) || "" + ); + } + } + } ); + }, + + hasClass: function( selector ) { + var className, elem, + i = 0; + + className = " " + selector + " "; + while ( ( elem = this[ i++ ] ) ) { + if ( elem.nodeType === 1 && + ( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) { + return true; + } + } + + return false; + } +} ); + +} ); diff --git a/test/fixtures/profile/javascript/jquery-small-after.js b/test/fixtures/profile/javascript/jquery-small-after.js new file mode 100644 index 000000000..e337a7940 --- /dev/null +++ b/test/fixtures/profile/javascript/jquery-small-after.js @@ -0,0 +1,56 @@ +// Use the right jQuery source on the test page (and iframes) +( function() { + /* global loadTests: false */ + + var path = window.location.pathname.split( "test" )[ 0 ], + QUnit = window.QUnit || parent.QUnit, + require = window.require || parent.require, + + // Default to unminified jQuery for directly-opened iframes + urlParams = QUnit ? + QUnit.urlParams : + { dev: true }, + src = urlParams.dev ? + "dist/jquery.js" : + "dist/jquery.min.js"; + + // Define configuration parameters controlling how jQuery is loaded + if ( QUnit ) { + QUnit.config.urlConfig.push( { + id: "amd", + label: "Load with AMD", + tooltip: "Load the AMD jQuery file (and its dependencies)" + } ); + QUnit.config.urlConfig.push( { + id: "dev", + label: "Load unminified", + tooltip: "Load the development (unminified) jQuery file" + } ); + } + + // Honor AMD loading on the main window (detected by seeing QUnit on it). + // This doesn't apply to iframes because they synchronously expect jQuery to be there. + if ( urlParams.amd && window.QUnit ) { + require.config( { + baseUrl: path + } ); + src = "src/jquery"; + + // Include tests if specified + if ( typeof loadTests !== "undefined" ) { + require( [ src ], loadTests ); + } else { + require( [ src ] ); + } + + // Otherwise, load synchronously + } else { + document.write( "