{"action":"created","issue":{"url":"https://api.github.com/repos/mjmeintjes/boot-react-native/issues/23","labels_url":"https://api.github.com/repos/mjmeintjes/boot-react-native/issues/23/labels{/name}","comments_url":"https://api.github.com/repos/mjmeintjes/boot-react-native/issues/23/comments","events_url":"https://api.github.com/repos/mjmeintjes/boot-react-native/issues/23/events","html_url":"https://github.com/mjmeintjes/boot-react-native/issues/23","id":127562980,"number":23,"title":"Add and test source map support","user":{"login":"mjmeintjes","id":72253,"avatar_url":"https://avatars.githubusercontent.com/u/72253?v=3","gravatar_id":"","url":"https://api.github.com/users/mjmeintjes","html_url":"https://github.com/mjmeintjes","followers_url":"https://api.github.com/users/mjmeintjes/followers","following_url":"https://api.github.com/users/mjmeintjes/following{/other_user}","gists_url":"https://api.github.com/users/mjmeintjes/gists{/gist_id}","starred_url":"https://api.github.com/users/mjmeintjes/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mjmeintjes/subscriptions","organizations_url":"https://api.github.com/users/mjmeintjes/orgs","repos_url":"https://api.github.com/users/mjmeintjes/repos","events_url":"https://api.github.com/users/mjmeintjes/events{/privacy}","received_events_url":"https://api.github.com/users/mjmeintjes/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":5,"created_at":"2016-01-19T23:21:14Z","updated_at":"2016-01-22T03:45:00Z","closed_at":null,"body":"Source maps are not currently being picked up correctly.\r\n\r\nhttps://github.com/mjmeintjes/boot-react-native/blob/master/resources/mattsum/boot_rn/js/cljs-rn-transformer.js#L19\r\nRN might be expecting source map contents instead of file name?\r\n\r\n"},"comment":{"url":"https://api.github.com/repos/mjmeintjes/boot-react-native/issues/comments/173796508","html_url":"https://github.com/mjmeintjes/boot-react-native/issues/23#issuecomment-173796508","issue_url":"https://api.github.com/repos/mjmeintjes/boot-react-native/issues/23","id":173796508,"user":{"login":"mjmeintjes","id":72253,"avatar_url":"https://avatars.githubusercontent.com/u/72253?v=3","gravatar_id":"","url":"https://api.github.com/users/mjmeintjes","html_url":"https://github.com/mjmeintjes","followers_url":"https://api.github.com/users/mjmeintjes/followers","following_url":"https://api.github.com/users/mjmeintjes/following{/other_user}","gists_url":"https://api.github.com/users/mjmeintjes/gists{/gist_id}","starred_url":"https://api.github.com/users/mjmeintjes/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mjmeintjes/subscriptions","organizations_url":"https://api.github.com/users/mjmeintjes/orgs","repos_url":"https://api.github.com/users/mjmeintjes/repos","events_url":"https://api.github.com/users/mjmeintjes/events{/privacy}","received_events_url":"https://api.github.com/users/mjmeintjes/received_events","type":"User","site_admin":false},"created_at":"2016-01-22T03:45:00Z","updated_at":"2016-01-22T03:45:00Z","body":"Hi\r\n\r\nI think I've gotten the source mapping to work (with a few caveats, see comments).\r\n\r\nThe reason for `build/node_modules` is that boot-react-native copies and renames modules generated by CLJS in order to work with React Native packager. See here for a more in-depth explanation: https://github.com/mjmeintjes/boot-react-native/blob/master/src/mattsum/boot_react_native.clj#L15\r\n\r\nHere's the code for the updated transformer. It turned out to be a little more complicated, because once you return the `.map` property for a module, RN starts to expect that property for all modules. Unfortunately, the base RN transformer does not provide the `.map` property, which causes Chrome to fail with `'sources' not found on undefined`.\r\n\r\nWhat I've done here is try to generate the `.map` property for all modules. This works on my PC for CLJS files, however Chrome does not seem to pick up the source maps for the JS files - luckily it falls back to just displaying the bundled JS, which is enough for our purpose.\r\n\r\n```\r\n/**\r\n * Copyright (c) 2015-present, Facebook, Inc.\r\n * All rights reserved.\r\n *\r\n * This source code is licensed under the BSD-style license found in the\r\n * LICENSE file in the root directory of this source tree. An additional grant\r\n * of patent rights can be found in the PATENTS file in the same directory.\r\n *\r\n * Note: This is a fork of the fb-specific transform.js\r\n */\r\n'use strict';\r\n\r\n// TODO: this should probably not be hardcoded\r\nconst fs = require('fs');\r\nconst transformer = require('react-native/packager/transformer');\r\n\r\nconst util = require('util');\r\nfunction getSourceMapModuleName(code) {\r\n    //Extract the source map module name from source code\r\n    var sourceMapRegex = /sourceMappingURL=(.*)\\.js\\.map/;\r\n    var match = sourceMapRegex.exec(code);\r\n    var moduleName = \"\";\r\n    if (match != null) {\r\n\t      moduleName = match[1] + \".cljs\";\r\n    }\r\n    return moduleName;\r\n}\r\nfunction transform(code, filename, callback) {\r\n    fs.readFile(filename + '.map', function (err, map) {\r\n        var sourceMap = err ?\r\n                getBasicSourceMap(filename, code) :\r\n                JSON.parse(map.toString());\r\n\r\n        sourceMap.sources = [getSourceMapModuleName(code)];\r\n\r\n        //Hardcode the root where our cljs files have been moved to\r\n        sourceMap.sourceRoot = \"/build/node_modules/\";\r\n        //Alternatively we could set sourcesContent to [<CONTENT OF CLJS FILE>]\r\n\r\n        callback(null, {\r\n            code: code.replace(\"# sourceMappingURL=\", \"\"),\r\n            map: sourceMap\r\n        });\r\n    });\r\n}\r\n\r\nfunction getBasicMappings(code) {\r\n    //TODO: This is copied from https://github.com/facebook/react-native/blob/528e30987aba8848f8c8815f00c42ecb2ce0919a/packager/react-packager/src/Bundler/Bundle.js#L265\r\n    //but unfortunately I know next to nothing about setting up source maps.\r\n    //Therefore it is not working. But, this is only run for js files, and Chrome falls\r\n    //back to displaying the Javascript from the bundled file anyway when it can't understand\r\n    //the source mappings from here.\r\n    //TLDR - I don't think this does anything, and it probably needs to be fixed, but not critical.\r\n    var mappings = \"\";\r\n    const line = 'AACA';\r\n    let lastCharNewLine  = false;\r\n    var moduleLines = 0;\r\n    for (let t = 0; t < code.length; t++) {\r\n        if (t === 0) {\r\n            mappings += 'AC';\r\n            mappings += 'A';\r\n        } else if (lastCharNewLine) {\r\n            moduleLines++;\r\n            mappings += line;\r\n        }\r\n        lastCharNewLine = code[t] === '\\n';\r\n        if (lastCharNewLine) {\r\n            mappings += ';';\r\n        }\r\n    }\r\n    mappings += ';';\r\n    return mappings;\r\n}\r\nfunction getBasicSourceMap(filename, code) {\r\n    //This is supposed to just provide a fallback sourcemap\r\n    //If we don't provide a source map for every module, then Google Chrome\r\n    //starts throwing errors ('sources' could not be found on undefined)\r\n    //Chrome expects every section (and there is a section for each module) to\r\n    //have a 'map' property with an array of 'sources'.\r\n\r\n    var mappings = getBasicMappings(code);\r\n    const map = {\r\n        file: filename,\r\n        sources: [filename],\r\n        version: 3,\r\n        names: [],\r\n        mappings: mappings,\r\n        sourcesContent: [code]\r\n    };\r\n    return map;\r\n}\r\n\r\nmodule.exports = function (data, callback) {\r\n    if (data.sourceCode && data.sourceCode.indexOf('Compiled by ClojureScript') > -1) {\r\n        transform(data.sourceCode, data.filename, callback);\r\n    } else {\r\n        var cb = function(err, mod) {\r\n            mod.map = getBasicSourceMap(data.filename, mod.code);\r\n            return callback(err,  mod);\r\n        };\r\n        transformer(data, cb);\r\n    }\r\n};\r\n```"}}