or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

context.mdextraction.mdindex.mdpaths.mdtraversal.md

context.mddocs/

0

# Traversal Context

1

2

When using callback functions with traversal methods (`forEach`, `map`, `reduce`), the `this` context provides extensive information about the current node and methods for modifying the traversal behavior.

3

4

## Context Properties

5

6

The callback's `this` object contains the following properties that describe the current traversal state:

7

8

### Node Information

9

10

```javascript { .api }

11

// Current node being visited

12

this.node // Current node value

13

this.node_ // Original node value (before modifications)

14

15

// Path information

16

this.path // Array of keys from root to current node

17

this.key // Property key of current node in its parent (undefined for root)

18

19

// Hierarchy information

20

this.parent // Parent context object (undefined for root)

21

this.parents // Array of all parent contexts

22

this.keys // Array of enumerable keys of current node (null for non-objects)

23

this.removedKeys // Object tracking keys removed from parent during traversal

24

```

25

26

### State Flags

27

28

```javascript { .api }

29

// Position flags

30

this.isRoot // boolean - Whether current node is the root

31

this.notRoot // boolean - Whether current node is not the root

32

this.isLeaf // boolean - Whether current node has no children

33

this.notLeaf // boolean - Whether current node has children

34

this.level // number - Depth of current node (0 for root)

35

36

// Traversal state

37

this.circular // Parent context if node creates circular reference, null otherwise

38

this.isFirst // boolean - Whether this is first child of parent (set during traversal)

39

this.isLast // boolean - Whether this is last child of parent (set during traversal)

40

```

41

42

## Context Methods

43

44

The context provides methods for modifying nodes and controlling traversal flow:

45

46

### Node Modification

47

48

```javascript { .api }

49

/**

50

* Update the current node value

51

* @param {*} value - New value for the node

52

* @param {boolean} [stopHere=false] - Whether to stop traversing this branch

53

*/

54

this.update(value, stopHere)

55

56

/**

57

* Remove current node (splice from arrays, delete from objects)

58

* @param {boolean} [stopHere=false] - Whether to stop traversing this branch

59

*/

60

this.remove(stopHere)

61

62

/**

63

* Delete current node (uses delete operator even on arrays)

64

* @param {boolean} [stopHere=false] - Whether to stop traversing this branch

65

*/

66

this.delete(stopHere)

67

```

68

69

### Traversal Control

70

71

```javascript { .api }

72

/**

73

* Register function to call before traversing children of current node

74

* @param {Function} fn - Function to call before children

75

*/

76

this.before(fn)

77

78

/**

79

* Register function to call after traversing children of current node

80

* @param {Function} fn - Function to call after children

81

*/

82

this.after(fn)

83

84

/**

85

* Register function to call before each child of current node

86

* @param {Function} fn - Function to call before each child

87

*/

88

this.pre(fn)

89

90

/**

91

* Register function to call after each child of current node

92

* @param {Function} fn - Function to call after each child

93

*/

94

this.post(fn)

95

96

/**

97

* Stop the entire traversal immediately

98

*/

99

this.stop()

100

101

/**

102

* Skip traversing children of the current node

103

*/

104

this.block()

105

```

106

107

## Usage Examples

108

109

### Basic Context Usage

110

111

```javascript

112

const traverse = require('traverse');

113

114

const obj = { a: { b: { c: 1 } }, d: [2, 3] };

115

116

traverse(obj).forEach(function (x) {

117

console.log('Path:', this.path);

118

console.log('Key:', this.key);

119

console.log('Value:', this.node);

120

console.log('Is leaf:', this.isLeaf);

121

console.log('Level:', this.level);

122

console.log('---');

123

});

124

125

// Output shows path and context info for each node:

126

// Path: [] Key: undefined Value: {a: {...}, d: [...]} Is leaf: false Level: 0

127

// Path: ['a'] Key: 'a' Value: {b: {...}} Is leaf: false Level: 1

128

// Path: ['a','b'] Key: 'b' Value: {c: 1} Is leaf: false Level: 2

129

// etc...

130

```

131

132

### Node Modification

133

134

```javascript

135

const traverse = require('traverse');

136

137

// Transform values based on context

138

const obj = {

139

numbers: [1, 2, 3],

140

nested: { value: 4 }

141

};

142

143

traverse(obj).forEach(function (x) {

144

if (typeof x === 'number') {

145

// Double numbers at even levels, triple at odd levels

146

const multiplier = this.level % 2 === 0 ? 2 : 3;

147

this.update(x * multiplier);

148

}

149

});

150

```

151

152

### Conditional Removal

153

154

```javascript

155

const traverse = require('traverse');

156

157

const obj = {

158

items: [1, null, 2, undefined, 3, '', 4],

159

nested: { a: null, b: 5, c: undefined }

160

};

161

162

// Remove falsy values

163

traverse(obj).forEach(function (x) {

164

if (!x && x !== 0 && x !== false) {

165

this.remove();

166

}

167

});

168

```

169

170

### Array vs Object Deletion

171

172

```javascript

173

const traverse = require('traverse');

174

175

const obj = {

176

arr: ['a', 'remove', 'b'],

177

obj: { keep: 1, remove: 2, keep2: 3 }

178

};

179

180

traverse(obj).forEach(function (x) {

181

if (x === 'remove' || x === 2) {

182

if (Array.isArray(this.parent.node)) {

183

this.remove(); // Splice from array

184

} else {

185

this.delete(); // Delete from object

186

}

187

}

188

});

189

```

190

191

### Traversal Control

192

193

```javascript

194

const traverse = require('traverse');

195

196

const obj = {

197

public: { data: 1, more: 2 },

198

private: { secret: 'hidden', confidential: 'data' },

199

normal: 'value'

200

};

201

202

// Skip traversing private sections

203

traverse(obj).forEach(function (x) {

204

if (this.key === 'private') {

205

console.log('Skipping private section');

206

this.block(); // Don't traverse children

207

} else {

208

console.log('Processing:', this.path, this.node);

209

}

210

});

211

```

212

213

### Before/After Hooks

214

215

```javascript

216

const traverse = require('traverse');

217

218

const obj = { a: { b: [1, 2] }, c: 3 };

219

220

traverse(obj).forEach(function (x) {

221

if (typeof x === 'object' && x !== null) {

222

this.before(function (node) {

223

console.log('About to traverse:', this.path);

224

});

225

226

this.after(function (node) {

227

console.log('Finished traversing:', this.path);

228

});

229

}

230

});

231

```

232

233

### Circular Reference Detection

234

235

```javascript

236

const traverse = require('traverse');

237

238

const obj = { name: 'parent' };

239

obj.self = obj; // Create circular reference

240

241

traverse(obj).forEach(function (x) {

242

if (this.circular) {

243

console.log('Found circular reference at path:', this.path);

244

console.log('Points back to path:', this.circular.path);

245

// this.circular is the parent context that creates the cycle

246

}

247

});

248

```

249

250

### Path-Based Operations

251

252

```javascript

253

const traverse = require('traverse');

254

255

const config = {

256

database: { host: 'localhost', port: 5432 },

257

cache: { host: 'redis-server', port: 6379 },

258

api: { version: 'v1', timeout: 5000 }

259

};

260

261

// Update all host values to production hosts

262

traverse(config).forEach(function (x) {

263

if (this.key === 'host' && this.path.length === 2) {

264

const service = this.path[0]; // 'database', 'cache', etc.

265

this.update(`prod-${service}.example.com`);

266

}

267

});

268

```

269

270

## Advanced Context Usage

271

272

### Custom Property Ordering

273

274

```javascript

275

const traverse = require('traverse');

276

277

const obj = { c: 1, a: 2, b: 3 };

278

279

traverse(obj).forEach(function (x) {

280

if (typeof x === 'object' && x !== null) {

281

this.before(function () {

282

// Sort keys alphabetically before traversing

283

if (this.keys) {

284

this.keys.sort();

285

}

286

});

287

}

288

});

289

```

290

291

### Conditional Stopping

292

293

```javascript

294

const traverse = require('traverse');

295

296

let found = false;

297

const obj = {

298

level1: {

299

level2: {

300

target: 'FOUND',

301

other: 'data'

302

}

303

}

304

};

305

306

traverse(obj).forEach(function (x) {

307

if (x === 'FOUND') {

308

console.log('Found target at:', this.path);

309

found = true;

310

this.stop(); // Stop entire traversal

311

}

312

});

313

```