SlideShare a Scribd company logo
JavaScript and the AST
Jarrod Overson - Shape Security
@jsoverson
var jQuery = require('jquery')
(function(){
//browserify stuff
})({
1: [function(require, module, exports) {
var jQuery = require('jquery');
}, { "jquery": 2 }],
2: [function(require, module, exports) {
//*! jQuery v1.11.3 | (c) 2005, 2015 jQuery
!function(a,b){"object"==typeof module&&"object
}, {}]
}, {}, [1]);
(function(){
//browserify stuff
})({
1: [function(require, module, exports) {
var jQuery = require('jquery');
}, { "jquery": 2 }],
2: [function(require, module, exports) {
//*! jQuery v1.11.3 | (c) 2005, 2015 jQuery
!function(a,b){"object"==typeof module&&"object
}, {}]
}, {}, [1]);
(function(){
//browserify stuff
})({
1: [function(require, module, exports) {
var jQuery = require('jquery');
}, { "jquery": 2 }],
2: [function(require, module, exports) {
//*! jQuery v1.11.3 | (c) 2005, 2015 jQuery
!function(a,b){"object"==typeof module&&"object
}, {}]
}, {}, [1]);
Less this
More this
var jQuery = require('jquery')
// var jQuery = require('jquery')
/*
// */ var jQuery = require('jquery');
var jQuery = "require('jquery')"
var module = 'jquery';
var jQuery = require(module)
files.map(file => file.ext))
files.map(function (file) {
return file.ext;
})
files.map(file => file.ext))
files.map(file => this.parse(file));
var _this = this;
files.map(function (file) {
return _this.parse(file);
});
Let's say you wanted to tweak your code.
Just a little bit.
foo(a,b)
Maybe…
bar(b,a)
Meh.
I got RegExes.
Remember life before RegExes?
Has anyone thought : "Meh, I got text search."
/foo()/
foo()
foo(a)
/foos*((:?[_$a-zA-Z][_$a-zA-
Z0-9]*|,)*?)/
foo(ಠ_ಠ)
/foo(([_$a-zA-ZxA0-uFFFF][_
$a-zA-Z0-9xA0-uFFFF]*)?)/
foo(4)
/foo((:?d*|[_$a-zA-ZxA0-
uFFFF][_$a-zA-Z0-9xA0-
uFFFF]*)?)/
foo(4,a)
/foo((:?d*|[_$a-zA-ZxA0-
uFFFF][_$a-zA-Z0-9xA0-
uFFFF]*|,)*?)/
foo (4,a)
/foos*((:?d*|[_$a-zA-ZxA0-
uFFFF][_$a-zA-Z0-9xA0-
uFFFF]*|,)*?)/
otherfoo()
bfoos*((:?d*|[_$a-zA-ZxA0-
uFFFF][_$a-zA-Z0-9xA0-
uFFFF]*|,)*?)
foo("2")
/bfoos*((:?(['"])[^2]*2|
d*|[_$a-zA-ZxA0-uFFFF][_$a-
zA-Z0-9xA0-uFFFF]*|,)*?)/
foo(''.prototype.toUpperCase.call([a
,""",b,"""].join('')))
/(╯°□°)╯︵ ┻━┻/
Using esquery:
[callee.name="foo"]
Ok. Ok. What's an AST?
Abstract Syntax Tree
A tree representation of the syntactic structure of source code.
• How do you get a JavaScript AST?
• How do you use it?
• How do you transform it?
• Building a transpiler.
Parsing JavaScript
• Esprima - Fast, conservative. Parses to ESTree format.
• Acorn - Error tolerant. Parses to ESTree format.
• Shift - Most spec-compliant. Parses to Shift format.
ESTree Shift
• Community effort
• Wide tool support
• Somewhat backwards 

compatible with 

SpiderMonkey AST
• Shape Security product
• Limited tool support
• Not compatible with ESTree
• Cross platform
• First spec-based AST
vs
Standardized AST formats
Why ever use Shift?
• Shift was developed by Ariya Hidayat (Esprima), Michael Ficarra
(CoffeeScript, loads of ES tools), and several others.
• Shift was designed specifically for simpler and more efficient
transformation and analysis code.
• Shift creators still contribute to ESTree.
• When in doubt, use ESTree for the community.
• If ESTree causes problems, consider Shift.
let ast = parse(source);
Just a Plain Old
JavaScript Object
{
"type": "Script",
"directives": [],
"statements": [
{
"type": "VariableDeclarationStatement",
"declaration": {
"type": "VariableDeclaration",
"kind": "var",
"declarators": [
{
"type": "VariableDeclarator",
"binding": {
"type": "BindingIdentifier",
"name": "a"
},
"init": {
"type": "CallExpression",
"callee": {
"type": "FunctionExpression",
"isGenerator": false,
"name": null,
"params": {
"type": "FormalParameters",
"items": [
{
"type": "BindingIdentifier",
"name": "a"
}
],
AST Explorer
http://felix-kling.de/esprima_ast_explorer/
Ready made traversal tools/helpers
• estraverse (estree)
• esprima-walk (estree)
• ast-traverse (estree)
• shift-traverse (shift)
• shift-reducer (shift)
How do you transform an AST?
let a = 2;
let b = 2;
How do you transform an AST?
{ type: 'Script',
directives: [],
statements:
[ { type: 'VariableDeclarationStatement',
declaration:
{ type: 'VariableDeclaration',
kind: 'let',
declarators:
[ { type: 'VariableDeclarator',
binding: { type: 'BindingIdentifier', name: 'a' },
init: { type: 'LiteralNumericExpression', value: 2 }
How do you transform an AST?
import {parseScript} from 'shift-parser';
import codegen from 'shift-codegen';
let ast = parse('let a = 2;');
ast.
statements[0].
declaration.
declarators[0].
binding.name = 'b';
let newSource = codegen(ast);
OK, Let's build a transpiler.
I really really like Arrow Expressions, how 'bout you?
Test first: what are we expecting?
(() => { return 2 })()
If we run* the following in an ES5 environment
it will return
2
* transpile and eval()
shift-reducer
Like [].reduce() but for ASTs
import reduce from 'shift-reducer';
var result = reduce(reducer, ast);
import spec from 'shift-spec';
let reducer = {};
for (var nodeName in spec) {
reducer["reduce" + nodeName] = function (node, state) {
return state;
};
}
Hypothesis:
(function(){ return 2 })()
Transforming the ArrowExpression into a FunctionExpression, eg
should pass the test.
JavaScript and the AST
JavaScript and the AST
reducer.reduceArrowExpression = function(node, state) {
state.type = 'FunctionExpression';
return state;
}
(function(){return 2}())
(()=>{return 2})()
Easy peasy.
Next step, omit the return.
(() => 2)()
JavaScript and the AST
JavaScript and the AST
reduceArrowExpression(node, state) {
state.type = 'FunctionExpression';
if (state.body.type !== 'FunctionBody') {
var oldBody = state.body;
state.body = {
type : 'FunctionBody',
directives : [],
statements : [{
type: 'ReturnStatement',
expression: oldBody
}]
}
}
return state;
}
(function(){return 2}())
(() => 2)()
JavaScript and the AST
And now for this
() => this.foo
The good way…
// assign "this" to a temporary variable
var _this = this;
// before we access it here
function(){ return _this.foo }
The easy way…
function(){ return this.foo }.bind(this)
(The good way is left as an exercise to you, mostly due to time)
ArrowExpressions && bind()
this.val = 2;
arrow = () => this.val;
arrow()
arrow.bind({val:6})()
obj = { val : 12, arrow : arrow }
obj.arrow();
// 2
// 2
// 2
FunctionExpressions && bind()
this.val = 2;
fn = function() { return this.val };
fn()
fn.bind({val:6})()
obj = { val : 12, fn : fn }
obj.fn();
// 2
// 6
// 12
function(){ return this.foo }.bind(this)
FunctionExpression
function(){ return this.foo }.bind(this)
CallExpression
FunctionExpression
reduceArrowExpression(node, state) {
state.type = 'FunctionExpression';
let callExpression = {
type: 'CallExpression',
callee: {
type: 'StaticMemberExpression',
object: state,
property: 'bind'
},
arguments: [{ type: 'ThisExpression' }]
};
if (state.body.type !== 'FunctionBody') {
var oldBody = state.body;
state.body = {
type : 'FunctionBody',
directives : [],()
reduceArrowExpression(node, state) {
state.type = 'FunctionExpression';
let callExpression = {
type: 'CallExpression',
callee: {
type: 'StaticMemberExpression',
object: state,
property: 'bind'
},
arguments: [{ type: 'ThisExpression' }]
};
if (state.body.type !== 'FunctionBody') {
var oldBody = state.body;
state.body = {
type : 'FunctionBody',
directives : [],<state>.bind()
{
type: "CallExpression",
callee: {
type: "StaticMemberExpression",
object: {
type: "IdentifierExpression",
name: "foo"
},
property: "bind"
},
arguments: []
}
foo.bind()
AST BREAK!
{
type: "CallExpression",
callee: {
type: "ComputedMemberExpression",
object: {
type:"IdentifierExpression",
name:"foo"
},
expression: {
type: "LiteralStringExpression",
value: "bind"
}
},
arguments: []
}
foo["bind"]()
AST BREAK!
{
type: "CallExpression",
callee: {
type: "IdentifierExpression",
name: "foo"
},
arguments: []
}
foo()
AST BREAK!
reduceArrowExpression(node, state) {
state.type = 'FunctionExpression';
let callExpression = {
type: 'CallExpression',
callee: {
type: 'StaticMemberExpression',
object: state,
property: 'bind'
},
arguments: [{ type: 'ThisExpression' }]
};
if (state.body.type !== 'FunctionBody') {
var oldBody = state.body;
state.body = {
type : 'FunctionBody',
directives : [],<state>.bind()
reduceArrowExpression(node, state) {
state.type = 'FunctionExpression';
let callExpression = {
type: 'CallExpression',
callee: {
type: 'StaticMemberExpression',
object: state,
property: 'bind'
},
arguments: [{ type: 'ThisExpression' }]
};
if (state.body.type !== 'FunctionBody') {
var oldBody = state.body;
state.body = {
type : 'FunctionBody',
directives : [],<state>.bind(this)
},
arguments: [{ type: 'ThisExpression' }]
};
if (state.body.type !== 'FunctionBody') {
var oldBody = state.body;
state.body = {
type : 'FunctionBody',
directives : [],
statements : [{
type: 'ReturnStatement',
expression: oldBody
]
}
}
return callExpression;
}
"use strict";
import spec from 'shift-spec';
let reducer = {};
for (var nodeName in spec) {
reducer['reduce' + nodeName] = (node, state) => state;
}
reducer.reduceArrowExpression = function (node, state) {
let callExpression = {
type: 'CallExpression',
callee: {
type: 'StaticMemberExpression',
object: state,
property: 'bind'
},
arguments: [{type: 'ThisExpression'}]
};
state.type = 'FunctionExpression';
if (state.body.type !== 'FunctionBody') {
let oldBody = state.body;
state.body = {
type: 'FunctionBody',
directives: [],
statements: [
{
type: 'ReturnStatement',
expression: oldBody
}
]
}
}
return callExpression;
};
export default reducer;
import {parseScript} from 'shift-parser';
import reduce from 'shift-reducer';
import codegen from 'shift-codegen';
import transpiler from './transpiler';
let ast = parseScript(source);
var result = reduce(transpiler, ast);
var newSource = codegen(result);
console.log(newSource);
Neato! Now what?
Analyze Transform
• Linting
• Complexity
• Auto Documentation
• Type Checking
• API Conformance
• Transpiling
• Code generation
• Preprocessing
• Refactoring
• Reformatting
What can you do with an AST?
"The worst mistake man ever
committed was treating
source code as text."
- John Stamos
Season 3, episode 20 of "Full House"
When have you ever typed this
function greet(target) {
}
without this?
Have you ever been concerned about this string?
function greet(target) {
}
JavaScript and the AST
JavaScript and the AST
JavaScript and the AST
Jarrod Overson - Shape Security
@jsoverson

More Related Content

What's hot (20)

PDF
Workshop 10: ECMAScript 6
Visual Engineering
 
PDF
Workshop 5: JavaScript testing
Visual Engineering
 
PDF
Proxies are Awesome!
Brendan Eich
 
PDF
FalsyValues. Dmitry Soshnikov - ECMAScript 6
Dmitry Soshnikov
 
PDF
Building fast interpreters in Rust
Ingvar Stepanyan
 
PDF
Say It With Javascript
Giovanni Scerra ☃
 
PDF
Powerful JavaScript Tips and Best Practices
Dragos Ionita
 
PDF
JavaScript Unit Testing with Jasmine
Raimonds Simanovskis
 
PDF
Testing your javascript code with jasmine
Rubyc Slides
 
PDF
PHP Performance Trivia
Nikita Popov
 
PDF
Letswift18 워크숍#1 스위프트 클린코드와 코드리뷰
Jung Kim
 
PDF
PHP Language Trivia
Nikita Popov
 
PDF
Typed Properties and more: What's coming in PHP 7.4?
Nikita Popov
 
PDF
Nikita Popov "What’s new in PHP 8.0?"
Fwdays
 
PDF
Min-Maxing Software Costs - Laracon EU 2015
Konstantin Kudryashov
 
PDF
JavaScript Design Patterns
Derek Brown
 
PPTX
5 Tips for Better JavaScript
Todd Anglin
 
PDF
Unbreakable: The Craft of Code
Joe Morgan
 
PDF
Being functional in PHP (DPC 2016)
David de Boer
 
PDF
async/await Revisited
Riza Fahmi
 
Workshop 10: ECMAScript 6
Visual Engineering
 
Workshop 5: JavaScript testing
Visual Engineering
 
Proxies are Awesome!
Brendan Eich
 
FalsyValues. Dmitry Soshnikov - ECMAScript 6
Dmitry Soshnikov
 
Building fast interpreters in Rust
Ingvar Stepanyan
 
Say It With Javascript
Giovanni Scerra ☃
 
Powerful JavaScript Tips and Best Practices
Dragos Ionita
 
JavaScript Unit Testing with Jasmine
Raimonds Simanovskis
 
Testing your javascript code with jasmine
Rubyc Slides
 
PHP Performance Trivia
Nikita Popov
 
Letswift18 워크숍#1 스위프트 클린코드와 코드리뷰
Jung Kim
 
PHP Language Trivia
Nikita Popov
 
Typed Properties and more: What's coming in PHP 7.4?
Nikita Popov
 
Nikita Popov "What’s new in PHP 8.0?"
Fwdays
 
Min-Maxing Software Costs - Laracon EU 2015
Konstantin Kudryashov
 
JavaScript Design Patterns
Derek Brown
 
5 Tips for Better JavaScript
Todd Anglin
 
Unbreakable: The Craft of Code
Joe Morgan
 
Being functional in PHP (DPC 2016)
David de Boer
 
async/await Revisited
Riza Fahmi
 

Viewers also liked (8)

PDF
Shape Security @ WaffleJS October 16
Jarrod Overson
 
PDF
How to Stop Man in the Browser Attacks
Imperva
 
PDF
AppSec California 2017 CSP: The Good, the Bad and the Ugly
Eli Nesterov
 
PPTX
Self Defending Applications
Michael Coates
 
PDF
Detecting headless browsers
Sergey Shekyan
 
PPTX
What is symbol table?
Satyamevjayte Haxor
 
PDF
CSW2017 Weston miller csw17_mitigating_native_remote_code_execution
CanSecWest
 
PPTX
Symbol table design (Compiler Construction)
Tech_MX
 
Shape Security @ WaffleJS October 16
Jarrod Overson
 
How to Stop Man in the Browser Attacks
Imperva
 
AppSec California 2017 CSP: The Good, the Bad and the Ugly
Eli Nesterov
 
Self Defending Applications
Michael Coates
 
Detecting headless browsers
Sergey Shekyan
 
What is symbol table?
Satyamevjayte Haxor
 
CSW2017 Weston miller csw17_mitigating_native_remote_code_execution
CanSecWest
 
Symbol table design (Compiler Construction)
Tech_MX
 
Ad

Similar to JavaScript and the AST (20)

PDF
Casting for not so strange actors
zucaritask
 
PDF
Security Challenges in Node.js
Websecurify
 
PDF
Serializing EMF models with Xtext
meysholdt
 
PDF
Java Script Workshop
Dmitry Baranovskiy
 
PPTX
jQuery Data Manipulate API - A source code dissecting journey
Huiyi Yan
 
PDF
Coding Ajax
Ted Husted
 
PDF
Coding Ajax
Ted Husted
 
PDF
Swift, functional programming, and the future of Objective-C
Alexis Gallagher
 
PPTX
Taming that client side mess with Backbone.js
Jarod Ferguson
 
PDF
Understanding backbonejs
Nick Lee
 
PDF
Scala - just good for Java shops?
Sarah Mount
 
PDF
Backbone.js — Introduction to client-side JavaScript MVC
pootsbook
 
PDF
international PHP2011_Bastian Feder_jQuery's Secrets
smueller_sandsmedia
 
PDF
jQuery secrets
Bastian Feder
 
PPTX
ES6 Overview
Bruno Scopelliti
 
PDF
Intro to Sail.js
Nicholas McClay
 
PDF
前端MVC 豆瓣说
Ting Lv
 
PDF
Bonnes pratiques de développement avec Node js
Francois Zaninotto
 
ODP
Groovy Ast Transformations (greach)
HamletDRC
 
PPTX
An introduction to scala
Xing
 
Casting for not so strange actors
zucaritask
 
Security Challenges in Node.js
Websecurify
 
Serializing EMF models with Xtext
meysholdt
 
Java Script Workshop
Dmitry Baranovskiy
 
jQuery Data Manipulate API - A source code dissecting journey
Huiyi Yan
 
Coding Ajax
Ted Husted
 
Coding Ajax
Ted Husted
 
Swift, functional programming, and the future of Objective-C
Alexis Gallagher
 
Taming that client side mess with Backbone.js
Jarod Ferguson
 
Understanding backbonejs
Nick Lee
 
Scala - just good for Java shops?
Sarah Mount
 
Backbone.js — Introduction to client-side JavaScript MVC
pootsbook
 
international PHP2011_Bastian Feder_jQuery's Secrets
smueller_sandsmedia
 
jQuery secrets
Bastian Feder
 
ES6 Overview
Bruno Scopelliti
 
Intro to Sail.js
Nicholas McClay
 
前端MVC 豆瓣说
Ting Lv
 
Bonnes pratiques de développement avec Node js
Francois Zaninotto
 
Groovy Ast Transformations (greach)
HamletDRC
 
An introduction to scala
Xing
 
Ad

More from Jarrod Overson (19)

PDF
Practical WebAssembly with Apex, wasmRS, and nanobus
Jarrod Overson
 
PDF
AppSecCali - How Credential Stuffing is Evolving
Jarrod Overson
 
PDF
How Credential Stuffing is Evolving - PasswordsCon 2019
Jarrod Overson
 
PDF
JSconf JP - Analysis of an exploited npm package. Event-stream's role in a su...
Jarrod Overson
 
PDF
Analysis of an OSS supply chain attack - How did 8 millions developers downlo...
Jarrod Overson
 
PDF
Deepfakes - How they work and what it means for the future
Jarrod Overson
 
PDF
The State of Credential Stuffing and the Future of Account Takeovers.
Jarrod Overson
 
PDF
How to Reverse Engineer Web Applications
Jarrod Overson
 
PDF
The life of breached data and the attack lifecycle
Jarrod Overson
 
PDF
The Life of Breached Data & The Dark Side of Security
Jarrod Overson
 
PDF
Graphics Programming for Web Developers
Jarrod Overson
 
PDF
The Dark Side of Security
Jarrod Overson
 
PDF
Maintainability SFJS Sept 4 2014
Jarrod Overson
 
PDF
Idiot proofing your code
Jarrod Overson
 
PDF
Riot on the web - Kenote @ QCon Sao Paulo 2014
Jarrod Overson
 
PDF
Managing JavaScript Complexity in Teams - Fluent
Jarrod Overson
 
PDF
Real World Web components
Jarrod Overson
 
PDF
Managing JavaScript Complexity
Jarrod Overson
 
PDF
Continuous Delivery for the Web Platform
Jarrod Overson
 
Practical WebAssembly with Apex, wasmRS, and nanobus
Jarrod Overson
 
AppSecCali - How Credential Stuffing is Evolving
Jarrod Overson
 
How Credential Stuffing is Evolving - PasswordsCon 2019
Jarrod Overson
 
JSconf JP - Analysis of an exploited npm package. Event-stream's role in a su...
Jarrod Overson
 
Analysis of an OSS supply chain attack - How did 8 millions developers downlo...
Jarrod Overson
 
Deepfakes - How they work and what it means for the future
Jarrod Overson
 
The State of Credential Stuffing and the Future of Account Takeovers.
Jarrod Overson
 
How to Reverse Engineer Web Applications
Jarrod Overson
 
The life of breached data and the attack lifecycle
Jarrod Overson
 
The Life of Breached Data & The Dark Side of Security
Jarrod Overson
 
Graphics Programming for Web Developers
Jarrod Overson
 
The Dark Side of Security
Jarrod Overson
 
Maintainability SFJS Sept 4 2014
Jarrod Overson
 
Idiot proofing your code
Jarrod Overson
 
Riot on the web - Kenote @ QCon Sao Paulo 2014
Jarrod Overson
 
Managing JavaScript Complexity in Teams - Fluent
Jarrod Overson
 
Real World Web components
Jarrod Overson
 
Managing JavaScript Complexity
Jarrod Overson
 
Continuous Delivery for the Web Platform
Jarrod Overson
 

Recently uploaded (20)

PDF
Agentic AI lifecycle for Enterprise Hyper-Automation
Debmalya Biswas
 
PPTX
AUTOMATION AND ROBOTICS IN PHARMA INDUSTRY.pptx
sameeraaabegumm
 
PDF
POV_ Why Enterprises Need to Find Value in ZERO.pdf
darshakparmar
 
PPTX
Future Tech Innovations 2025 – A TechLists Insight
TechLists
 
PPTX
The Project Compass - GDG on Campus MSIT
dscmsitkol
 
PDF
Achieving Consistent and Reliable AI Code Generation - Medusa AI
medusaaico
 
PDF
Advancing WebDriver BiDi support in WebKit
Igalia
 
PDF
IoT-Powered Industrial Transformation – Smart Manufacturing to Connected Heal...
Rejig Digital
 
PDF
Empower Inclusion Through Accessible Java Applications
Ana-Maria Mihalceanu
 
PDF
LOOPS in C Programming Language - Technology
RishabhDwivedi43
 
PDF
Smart Trailers 2025 Update with History and Overview
Paul Menig
 
DOCX
Cryptography Quiz: test your knowledge of this important security concept.
Rajni Bhardwaj Grover
 
PPTX
COMPARISON OF RASTER ANALYSIS TOOLS OF QGIS AND ARCGIS
Sharanya Sarkar
 
PPTX
OpenID AuthZEN - Analyst Briefing July 2025
David Brossard
 
PDF
[Newgen] NewgenONE Marvin Brochure 1.pdf
darshakparmar
 
PDF
Reverse Engineering of Security Products: Developing an Advanced Microsoft De...
nwbxhhcyjv
 
PDF
Transcript: New from BookNet Canada for 2025: BNC BiblioShare - Tech Forum 2025
BookNet Canada
 
PDF
Newgen 2022-Forrester Newgen TEI_13 05 2022-The-Total-Economic-Impact-Newgen-...
darshakparmar
 
PPTX
From Sci-Fi to Reality: Exploring AI Evolution
Svetlana Meissner
 
PDF
DevBcn - Building 10x Organizations Using Modern Productivity Metrics
Justin Reock
 
Agentic AI lifecycle for Enterprise Hyper-Automation
Debmalya Biswas
 
AUTOMATION AND ROBOTICS IN PHARMA INDUSTRY.pptx
sameeraaabegumm
 
POV_ Why Enterprises Need to Find Value in ZERO.pdf
darshakparmar
 
Future Tech Innovations 2025 – A TechLists Insight
TechLists
 
The Project Compass - GDG on Campus MSIT
dscmsitkol
 
Achieving Consistent and Reliable AI Code Generation - Medusa AI
medusaaico
 
Advancing WebDriver BiDi support in WebKit
Igalia
 
IoT-Powered Industrial Transformation – Smart Manufacturing to Connected Heal...
Rejig Digital
 
Empower Inclusion Through Accessible Java Applications
Ana-Maria Mihalceanu
 
LOOPS in C Programming Language - Technology
RishabhDwivedi43
 
Smart Trailers 2025 Update with History and Overview
Paul Menig
 
Cryptography Quiz: test your knowledge of this important security concept.
Rajni Bhardwaj Grover
 
COMPARISON OF RASTER ANALYSIS TOOLS OF QGIS AND ARCGIS
Sharanya Sarkar
 
OpenID AuthZEN - Analyst Briefing July 2025
David Brossard
 
[Newgen] NewgenONE Marvin Brochure 1.pdf
darshakparmar
 
Reverse Engineering of Security Products: Developing an Advanced Microsoft De...
nwbxhhcyjv
 
Transcript: New from BookNet Canada for 2025: BNC BiblioShare - Tech Forum 2025
BookNet Canada
 
Newgen 2022-Forrester Newgen TEI_13 05 2022-The-Total-Economic-Impact-Newgen-...
darshakparmar
 
From Sci-Fi to Reality: Exploring AI Evolution
Svetlana Meissner
 
DevBcn - Building 10x Organizations Using Modern Productivity Metrics
Justin Reock
 

JavaScript and the AST