-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathJDSL.ps1
executable file
·164 lines (154 loc) · 13.6 KB
/
JDSL.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
#!/usr/bin/env sh
"\"",`$(echo --% ' |out-null)" >$null;function :{};function dv{<#${/*'>/dev/null )` 2>/dev/null;dv() { #>
echo "1.42.1"; : --% ' |out-null <#'; }; version="$(dv)"; deno="$HOME/.deno/$version/bin/deno"; if [ -x "$deno" ]; then exec "$deno" run -q -A --no-lock "$0" "$@"; elif [ -f "$deno" ]; then chmod +x "$deno" && exec "$deno" run -q -A --no-lock "$0" "$@"; fi; bin_dir="$HOME/.deno/$version/bin"; exe="$bin_dir/deno"; has () { command -v "$1" >/dev/null; } ; if ! has unzip; then if ! has apt-get; then has brew && brew install unzip; else if [ "$(whoami)" = "root" ]; then apt-get install unzip -y; elif has sudo; then echo "Can I install unzip for you? (its required for this command to work) ";read ANSWER;echo; if [ "$ANSWER" = "y" ] || [ "$ANSWER" = "yes" ] || [ "$ANSWER" = "Y" ]; then sudo apt-get install unzip -y; fi; elif has doas; then echo "Can I install unzip for you? (its required for this command to work) ";read ANSWER;echo; if [ "$ANSWER" = "y" ] || [ "$ANSWER" = "yes" ] || [ "$ANSWER" = "Y" ]; then doas apt-get install unzip -y; fi; fi; fi; fi; if ! has unzip; then echo ""; echo "So I couldn't find an 'unzip' command"; echo "And I tried to auto install it, but it seems that failed"; echo "(This script needs unzip and either curl or wget)"; echo "Please install the unzip command manually then re-run this script"; exit 1; fi; repo="denoland/deno"; if [ "$OS" = "Windows_NT" ]; then target="x86_64-pc-windows-msvc"; else :; case $(uname -sm) in "Darwin x86_64") target="x86_64-apple-darwin" ;; "Darwin arm64") target="aarch64-apple-darwin" ;; "Linux aarch64") repo="LukeChannings/deno-arm64" target="linux-arm64" ;; "Linux armhf") echo "deno sadly doesn't support 32-bit ARM. Please check your hardware and possibly install a 64-bit operating system." exit 1 ;; *) target="x86_64-unknown-linux-gnu" ;; esac; fi; deno_uri="https://github.com/$repo/releases/download/v$version/deno-$target.zip"; exe="$bin_dir/deno"; if [ ! -d "$bin_dir" ]; then mkdir -p "$bin_dir"; fi; if ! curl --fail --location --progress-bar --output "$exe.zip" "$deno_uri"; then if ! wget --output-document="$exe.zip" "$deno_uri"; then echo "Howdy! I looked for the 'curl' and for 'wget' commands but I didn't see either of them. Please install one of them, otherwise I have no way to install the missing deno version needed to run this code"; exit 1; fi; fi; unzip -d "$bin_dir" -o "$exe.zip"; chmod +x "$exe"; rm "$exe.zip"; exec "$deno" run -q -A --no-lock "$0" "$@"; #>}; $DenoInstall = "${HOME}/.deno/$(dv)"; $BinDir = "$DenoInstall/bin"; $DenoExe = "$BinDir/deno.exe"; if (-not(Test-Path -Path "$DenoExe" -PathType Leaf)) { $DenoZip = "$BinDir/deno.zip"; $DenoUri = "https://github.com/denoland/deno/releases/download/v$(dv)/deno-x86_64-pc-windows-msvc.zip"; [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; if (!(Test-Path $BinDir)) { New-Item $BinDir -ItemType Directory | Out-Null; }; Function Test-CommandExists { Param ($command); $oldPreference = $ErrorActionPreference; $ErrorActionPreference = "stop"; try {if(Get-Command "$command"){RETURN $true}} Catch {Write-Host "$command does not exist"; RETURN $false}; Finally {$ErrorActionPreference=$oldPreference}; }; if (Test-CommandExists curl) { curl -Lo $DenoZip $DenoUri; } else { curl.exe -Lo $DenoZip $DenoUri; }; if (Test-CommandExists curl) { tar xf $DenoZip -C $BinDir; } else { tar -Lo $DenoZip $DenoUri; }; Remove-Item $DenoZip; $User = [EnvironmentVariableTarget]::User; $Path = [Environment]::GetEnvironmentVariable('Path', $User); if (!(";$Path;".ToLower() -like "*;$BinDir;*".ToLower())) { [Environment]::SetEnvironmentVariable('Path', "$Path;$BinDir", $User); $Env:Path += ";$BinDir"; } }; & "$DenoExe" run -q -A --no-lock "$PSCommandPath" @args; Exit $LastExitCode; <#
# */0}`;
// what this abomination at the top? see: https://github.com/jeff-hykin/deno-guillotine
import { FileSystem, glob } from "https://deno.land/x/quickr@0.6.31/main/file_system.js"
import { run, throwIfFails, zipInto, mergeInto, returnAsString, Timeout, Env, Cwd, Stdin, Stdout, Stderr, Out, Overwrite, AppendTo } from "https://deno.land/x/quickr@0.6.31/main/run.js"
import { Console, clearAnsiStylesFrom, black, white, red, green, blue, yellow, cyan, magenta, lightBlack, lightWhite, lightRed, lightGreen, lightBlue, lightYellow, lightMagenta, lightCyan, blackBackground, whiteBackground, redBackground, greenBackground, blueBackground, yellowBackground, magentaBackground, cyanBackground, lightBlackBackground, lightRedBackground, lightGreenBackground, lightYellowBackground, lightBlueBackground, lightMagentaBackground, lightCyanBackground, lightWhiteBackground, bold, reset, dim, italic, underline, inverse, strikethrough, gray, grey, lightGray, lightGrey, grayBackground, greyBackground, lightGrayBackground, lightGreyBackground, } from "https://deno.land/x/quickr@0.6.31/main/console.js"
import { regex, capitalize, indent, toCamelCase, digitsToEnglishArray, toPascalCase, toKebabCase, toSnakeCase, toScreamingtoKebabCase, toScreamingtoSnakeCase, toRepresentation, toString, escapeRegexMatch, escapeRegexReplace, extractFirst, isValidIdentifier } from "https://deno.land/x/good@1.3.0.4/string.js"
import { enumerate, zip } from "https://deno.land/x/good@1.3.0.4/array.js"
import { parserFromWasm, flatNodeList } from "https://deno.land/x/deno_tree_sitter@0.0.5/main.js"
import javascript from "https://github.com/jeff-hykin/common_tree_sitter_languages/raw/4d8a6d34d7f6263ff570f333cdcf5ded6be89e3d/main/javascript.js"
const parser = await parserFromWasm(javascript)
console.debug = ()=>0 // turn off debugging (Elegant I know)
try {
//
// gotta commit any current changes, otherwise how will we checkout commits for the function calls
//
await run`git add -A ${Stdout(null)}`
await run`git commit -m '--' ${Stdout(null)}`
const startingCommit = (await run`git rev-parse --abbrev-ref HEAD ${Stdout(returnAsString)}`).replace(/\n/g,"")
const classes = {}
FileSystem.cwd = Deno.args[0]
const filePaths = await FileSystem.listFileItemsIn(".")
for (const each of filePaths) {
if (each.path.endsWith(".json")) {
// console.group()
console.debug(`loading ${each.path}`)
const parentPath = FileSystem.parentPath(each.path)
// make sure back on master otherwise sometimes the .json file itself dissapears (didn't exist on older commit)
console.debug(`${await run`git checkout ${startingCommit} ${Out(returnAsString)}`}`)
const output = await FileSystem.read(each.path)
if (!output) {
console.debug(`each.path: ${each.path}`)
}
try {
var { File, Class, Author, Purpose, Functions } = JSON.parse(output)
} catch (error) {
console.debug(`await FileSystem.listFileItemsIn(FileSystem.parentPath(each.path)) is:`,await FileSystem.listFileItemsIn(FileSystem.parentPath(each.path)))
console.debug(`each.path is:`,each.path)
console.debug(`output is:`,output)
console.debug(`error is:`,error)
console.debug(await run`git checkout ${startingCommit} ${Out(returnAsString)}`)
console.debug(`continuing anyways!`)
continue
}
classes[Class] = eval(`(()=>{ class ${Class} {}; return ${Class} })()`)
const methods = {}
try {
console.debug(`{ File, Class, Author, Purpose, Functions } is:`,{ File, Class, Author, Purpose, Functions })
for (const eachFunctionNumber of Functions) {
// console.group()
const commitShortHash = eachFunctionNumber.toString(16).padStart(7,"0")
console.debug(`loading ${commitShortHash}`)
console.debug(` ${await run`git checkout ${commitShortHash} ${Out(returnAsString)}`}`)
const jsFile = await FileSystem.read(`${parentPath}/${each.name}.js`)
const methodName = jsFile.match(new RegExp(`${Class}\\.prototype\\.(\\w+)`))[1]
const jsWithRenamedClass = jsFile.replace(new RegExp(`\\b${Class}\\b`, "g"), `classes[${JSON.stringify(Class)}]`)
console.debug(`aka ${methodName}`)
const tree = parser.parse({ string: jsWithRenamedClass, withWhitespace: true })
let newCode = ""
const allNodes = flatNodeList(tree.rootNode).filter(each=>!each.hasChildren)
for (const [ nodeIndex, each ] of enumerate(allNodes)) {
if (!(each.type == "comment")) {
newCode += each.text||""
} else {
let text = each.text
const remainingText = allNodes.slice(nodeIndex+1,).filter(each=>each.type!=="comment").map(each=>each.text).join("")
// must try to make every bit of potentially-executable code executable
// slice off the comment-y punctuation stuff
if (text.startsWith("/*")) {
text = text.slice(2,-2)
} else {
text = text.slice(2)
}
// if it passes eval, then its valid code 😜
const snippetIsValid = async (snippet)=>{
try {
const proposedCode = `${newCode}${snippet}${remainingText}`
await eval(proposedCode)
newCode += snippet
return true
} catch (error) {
try {
// gotta try automatic semicolon injection
await eval(`${newCode};${snippet}${remainingText}`)
newCode += ";"+snippet
return true
} catch (error) {
return false
}
return false
}
return false
}
//
// gotta brute force try all the sub-stirng combinations to make sure we
// execute as comments as JDSL-y possible
//
tryNext: while (true) {
for (const [startIndex, _] of enumerate(text)) {
for (const [endIndex, __] of enumerate(text+" ").reverse()) {
if (await snippetIsValid(text.slice(startIndex, endIndex))) {
text = text.slice(endIndex)
// if there's still some text remaining, try to make it valid too
if (text.length != 0) {
continue tryNext
// otherwise we're done
} else {
break tryNext
}
}
}
}
break // ran out of characters
}
}
}
try {
// attach the method to the prototype
classes[Class].prototype[methodName] = methods[methodName] = eval(newCode).bind(classes[Class].prototype)
} catch (error) {
console.error(`code is:`,newCode)
console.error(`sending an email to ${Author}: ${Class}.json, ${eachFunctionNumber} aka ${JSON.stringify(methodName)} didnt work: ${error}`)
console.error(`error.stack is:`,error.stack)
}
// console.groupEnd()
}
// always call constructor if it exists
if (Object.keys(methods).includes("constructor")) {
try {
const newObject = new classes[Class]()
Object.assign(newObject, methods) // I shouldn't have to do this because
// the prototype already has these methods but whatever
// call the constructor
await methods.constructor.apply(newObject, [{}])
} catch (error) {
console.error(`sending an email to ${Author}: ${JSON.stringify("constructor")} didnt work: ${error}`)
console.error(`error.stack is:`,error.stack)
}
}
} catch (error) {
console.error(`sending an email to ${Author}: ${JSON.stringify(error)}, ${error}`)
console.error(`error.stack is:`,error.stack)
}
// console.groupEnd()
}
}
console.debug(`${await run`git checkout ${startingCommit} ${Out(returnAsString)}`}`)
console.debug("\nEND, returning")
} catch (error) {
await run`git checkout master`
}
// (this comment is part of deno-guillotine, dont remove) #>