useless
Version:
Use Less. Do More. JavaScript on steroids.
138 lines (86 loc) • 4.53 kB
JavaScript
;
/* ------------------------------------------------------------------------ */
const O = Object
/* ------------------------------------------------------------------------ */
_.hasReflection = true
/* ------------------------------------------------------------------------ */
$global.getSource = require ('get-source')
/* ------------------------------------------------------------------------ */
$global.StackTracey = O.assign (require ('stacktracey'), {
fromErrorWithAsync (e) {
let stackEntries = new StackTracey (e),
asyncContext = e.asyncContext
while (asyncContext) {
stackEntries = stackEntries.concat (new StackTracey (asyncContext.stack))
asyncContext = asyncContext.asyncContext }
return stackEntries.mergeRepeatedLines }
})
/* ------------------------------------------------------------------------ */
_.tests.reflection = {
'file paths': function () {
$assert (typeof $uselessPath, 'string')
$assert ($sourcePath .length > 0)
$assert ($uselessPath.length > 0) },
}
;(function () {
var currentFile = $platform.Browser
? ((new StackTracey ())[2] || { file: '' }).file
: __filename
$global.const ('$uselessPath', _.initial (currentFile.split ('/'), $platform.NodeJS ? 2 : 1).join ('/') + '/')
$global.const ('$sourcePath', (function () {
var local = ($uselessPath.match (/(.+)\/node_modules\/(.+)/) || [])[1]
return local ? (local + '/') : $uselessPath }) ())
}) ();
/* ------------------------------------------------------------------------ */
const asTable = require ('as-table')
StackTracey.prototype[Symbol.for ('String.ify')] = function (stringify) {
return asTable (this.map (entry => [
'\t' + 'at ' + entry.calleeShort.slice (0, 30),
(entry.fileShort && (entry.fileShort + ':' + entry.line)) || '',
((entry.sourceLine || '').trim () || '').slice (0, 80) ]))
}
Error.prototype[Symbol.for ('String.ify')] = function (stringify) {
try {
var stack = StackTracey.fromErrorWithAsync (this).slice (this.stackOffset || 0).clean
var why = stringify.limit ((this.message || '').replace (/\r|\n/g, '').trim (), 120)
return ('[EXCEPTION] ' + why +
(this.notMatching && ([].concat (this.notMatching).map (x => '\t' + stringify.noPretty (x)).join ('\n') + '\n\n') || '') +
'\n\n') + stringify (stack) + '\n' }
catch (sub) {
return 'YO DAWG I HEARD YOU LIKE EXCEPTIONS... SO WE THREW EXCEPTION WHILE PRINTING YOUR EXCEPTION:\n\n' + sub.stack +
'\n\nORIGINAL EXCEPTION:\n\n' + this.stack + '\n\n' }
}
/* ------------------------------------------------------------------------ */
_.tests.prototypeMeta = {
'Prototype.$meta': function () {
const DummyProto = $prototype ()
const DummyTrait = $trait ()
$assertMatches (DummyProto.$meta, { name: 'DummyProto', type: 'prototype' })
$assertMatches (DummyTrait.$meta, { name: 'DummyTrait', type: 'trait' })
},
'String.ify': function () {
const Dummy = $prototype ({})
$assert (String.ify (Dummy), 'Dummy ()')
}
}
;(() => {
const findMeta = stack => _.find2 (stack.withSources.reverse (), location => {
let match = location.sourceLine.match (/([A-z]+)\s*=\s*\$([A-Za-z0-9_]+)/)
return (match && { name: (match[1] === 'exports') ? location.fileName : match[1],
type: match[2],
file: location.fileShort }) || false
})
$prototype.macro (function (def, base) {
if (typeof Symbol !== 'undefined') {
def.constructor[Symbol.for ('String.ify')] = function () {
return ((this.$meta && this.$meta.name) || '<prototype>') + ' ()' }
}
/* NB: memoization is here because findMeta performs slow (needs to fetch sources and sourcemaps),
and we dont wanna do this at construction of each prototype. Better do this on first $meta request. */
if (!def.$meta) {
const stack = new StackTracey ()
def.$meta = $static ($property (_.memoize (() => findMeta (stack)))) }
return def
})
}) ();
/* ------------------------------------------------------------------------ */